より優れた指向で信頼性の高いUDPプロトコルを介して「ローカルホスト」に送信しようとしているDatagramPacketを作成しています(手動で作成:チェックサム、シーケンス番号、および長さを含むヘッダーを手動で追加していますデータ)、サーバーからの確認を待ちます。
最初はすべて問題ありませんでした。1 パケット長 (1000 バイト) のファイルもあれば、1000 バイトごとに 20 パケットのファイルもありましたが、問題はありませんでした。サーバーは正しい ACK (確認応答) で応答しました。すべてが大丈夫でした!しかし、どういうわけか、5分後、私のプログラムはファイルを送信しなくなり、1つのパケットのみを送信し、例外で停止します...
java.net.SocketTimeoutException: Receive timed out
at java.net.DualStackPlainDatagramSocketImpl.socketReceiveOrPeekData(Native Method)
at java.net.DualStackPlainDatagramSocketImpl.receive0(Unknown Source)
at java.net.AbstractPlainDatagramSocketImpl.receive(Unknown Source)
at java.net.DatagramSocket.receive(Unknown Source)
at blatt7.FileSender.sendFile(FileSender.java:100)
at blatt7.FileSender.main(FileSender.java:184)"
コードが長すぎて申し訳ありませんが、誰かが助けてくれれば、それは本当に良いことです!! ありがとうございました!ここに私のクライアントコードがあります:
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.file.*;
import java.util.zip.CRC32;
public class FileSender {
DatagramSocket sock = null;
CRC32 checksumRechner = new CRC32();
private byte[] readLength;
private byte[] seqNrArray;
private byte[] checksumArray;
private String dateiPfad;
private String zielRechner;
private InetAddress host;
private File datei;
private int seqNr = 1;
FileInputStream fis;
int counter = 0;
byte[] daten = new byte[1000];
byte[] header = new byte[16];
byte[] packet;
byte[] ack_buffer = new byte[4];
int port = 7777;
DatagramPacket dp;
DatagramPacket ack_dp = new DatagramPacket(ack_buffer, ack_buffer.length);
private long receivedSeqNr = 0;
private int readLen;
public FileSender(String zielRechner, String dateiPfad) throws IOException {
this.setZielRechner(zielRechner);
this.setDateiPfad(dateiPfad);
setHost(InetAddress.getByName(zielRechner));
setDatei(new File(dateiPfad));
fis = new FileInputStream(datei);
}
public void sendFile() throws IOException {
while((readLen = fis.read(daten)) != -1) {
if (getSeqNr() == 1)
seqNr = 0;
else
seqNr = 1;
readLength = intToBytes(readLen);
for (int i = 0; i < readLength.length; i++) {
header[8+i] = readLength[i];
}
seqNrArray = intToBytes(getSeqNr());
for (int i = 0; i <seqNrArray.length; i++) {
header[12+i] = seqNrArray[i];
}
packet = new byte[header.length + daten.length];
//wir fügen Daten und Header ins Packet zusammen.
int j=0;
for (int i=0; i<packet.length; i++) {
if (i < header.length)
packet[i] = header[i];
else {
packet[i] = daten[j];
j++;
}
}
//wir rechnen die prüfsumme
checksumRechner.reset();
checksumRechner.update(packet,8,8+readLen);
checksumArray = longToBytes(checksumRechner.getValue());
//wir schreiben uns checksum in das packet
for(int i=0; i < 8; i++) {
packet[i] = checksumArray[i];
}
dp = new DatagramPacket(packet , packet.length , host , port);
while (receivedSeqNr == seqNr) {
try {
sock = new DatagramSocket();
sock.send(dp);
sock.setSoTimeout(7000);
counter++;
System.out.println("Paket sent with seqNr: " + getSeqNr() + " und Length: " + getReadLen() + " - PAKET NR: " + counter);
sock.receive(ack_dp);
ack_buffer = ack_dp.getData();
receivedSeqNr = bytesToLong(ack_buffer,0);
System.out.println("got SeqNr, with receivedSeq-Nr: " + receivedSeqNr);
} catch (SocketTimeoutException e)
{
e.printStackTrace();
break;
}
}
}
fis.close();
}
public static byte[] longToBytes(long value) {
ByteBuffer buffer = ByteBuffer.allocate(8);
buffer.putLong(value);
return buffer.array();
}
public static long bytesToLong(byte[] bytes, int index) {
ByteBuffer buffer = ByteBuffer.allocate(8);
buffer.put(bytes);
buffer.flip();//need flip
return buffer.getLong(index);
}
public static byte[] intToBytes(int value) {
ByteBuffer buffer = ByteBuffer.allocate(4);
buffer.putInt(value);
return buffer.array();
}
public static int bytesToInt(byte[] bytes, int index) {
ByteBuffer buffer = ByteBuffer.allocate(4);
buffer.put(bytes);
buffer.flip();//need flip
return buffer.getInt(index);
}
public String getDateiPfad() {
return dateiPfad;
}
public void setDateiPfad(String dateiPfad2) {
this.dateiPfad = dateiPfad2;
}
public String getZielRechner() {
return zielRechner;
}
public void setZielRechner(String zielRechner) {
this.zielRechner = zielRechner;
}
public InetAddress getHost() {
return host;
}
public void setHost(InetAddress host) {
this.host = host;
}
public File getDatei() {
return datei;
}
public void setDatei(File datei) {
this.datei = datei;
}
public int getSeqNr() {
return seqNr;
}
public int getReadLen() {
return readLen;
}
public static void main(String[] args) throws IOException,ClassNotFoundException {
FileSender sender = new FileSender("localhost", "C:/Users/Kb/Desktop/wifi pops.txt");
sender.sendFile();
}
}
と私のサーバーのコード:
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.zip.CRC32;
パブリック クラス ファイルレシーバー {
static byte[] buffer;
DatagramPacket incoming;
DatagramSocket serverSock = null;
CRC32 checksumRechner = new CRC32();
int dataLength;
long checksumReceiver;
long checksumSender;
int port = 7777;
int receivedSeqNr;
public FileReceiver() {
buffer = new byte[1500];
incoming = new DatagramPacket(buffer, buffer.length);
}
public void receive() {
try
{
//1. Erstellung eines server sockets, parameter ist localportnummer
serverSock = new DatagramSocket(port);
serverSock.setSoTimeout(10000);
//2. Warten für incoming data
echo("Server socket created. Waiting for incoming data...");
//kommunikationsloop
while(true)
{
serverSock.receive(incoming);
byte[] dataLengthArray = new byte[4];
for (int i=0; i <4; i++) {
dataLengthArray[i] = buffer[i+8];
}
dataLength = FileSender.bytesToInt(dataLengthArray,0);
checksumRechner.reset();
checksumRechner.update(buffer, 8, dataLength+8);
checksumReceiver = checksumRechner.getValue();
byte[] receivedSeqNrArray = new byte[4];
for (int i=0; i <4; i++) {
receivedSeqNrArray[i] = buffer[i+12];
}
receivedSeqNr = FileSender.bytesToInt(receivedSeqNrArray,0);
byte[] receivedChecksumArray = new byte[8];
for (int i=0; i <8; i++) {
receivedChecksumArray[i] = buffer[i];
}
long receivedChecksumNr = FileSender.bytesToLong(receivedChecksumArray,0);
System.out.println("Paket received with checksum: " + receivedChecksumNr);
System.out.println("Server-generated checksum: " + checksumReceiver);
System.out.println("Paket got, with seqNr: " + receivedSeqNr + " und length: " + dataLength);
if (checksumReceiver != receivedChecksumNr) {
sendACK(receivedSeqNr);
System.out.println("Paket has errors! Must be sent again!");
}
else if(checksumReceiver == receivedChecksumNr && receivedSeqNr == 1) {
sendACK(0);
System.out.println("SeqNr sent --> SeqNr: 0");
}
else if (checksumReceiver == receivedChecksumNr && receivedSeqNr == 0) {
sendACK(1);
System.out.println("SeqNr sent --> SeqNr: 1");
}
}
}
catch(IOException e)
{
System.err.println("IOException " + e);
}
}
//echo data ausgeben
public static void echo(String msg)
{
System.out.println(msg);
}
public void sendACK(int seqNum) throws IOException {
byte[] sendArray = FileSender.intToBytes(seqNum);
DatagramPacket sendPacket = new DatagramPacket(sendArray, sendArray.length, InetAddress.getByName("localhost"), 7777);
serverSock.send(sendPacket);
}
public static void main(String[] args) throws IOException,ClassNotFoundException {
FileReceiver receiver = new FileReceiver();
receiver.receive();
}
}