我试着发送一个数据包,然后必须等待服务器的确认,这样我就知道是必须重新发送同一个数据包还是发送下一个数据包..
为此,我在客户端上使用相同的套接字来发送数据包和接收确认(ack),在服务器端使用相同的另一个套接字,用于接收数据包,然后向客户端发送确认。。
第一个问题是客户端正在发送数据包,服务器正在接收它,然后将确认发送到客户端,但客户端在接收确认数据包时阻塞。
我正在制作一些System.out.println来确定问题所在,但我找不到此问题的任何解决方案。
第二个问题是服务器仍然总是在接收数据,不要等待客户端发送东西,我检查了一下,因为我得到了那几行(比如“得到了长度为xxx的数据包”“ack发送了ackNr yyy”…“打印在服务器端,尽管客户端在发送第一个数据包后一直在阻塞,因为它在等待未收到的确认!
这是客户端的代码:
package blatt7;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.util.zip.CRC32;
public class FileSender {
String zielRechner;
String filePath;
InetAddress host;
File file;
FileInputStream fis;
int readLength;
int sequenceNr = 0;
int receivedSeqNr = 1;
static int port = 7777;
int packetNr = 0;
byte[] packet = new byte[1216];
byte[] data = new byte[1200];
byte[] header = new byte[16];
byte[] readLengthByte = new byte[4];
byte[] sequenceNrByte = new byte[4];
byte[] checksumByte = new byte[8];
byte[] ackBuffer = new byte[4];
CRC32 checksumCalculator = new CRC32();
DatagramPacket dp;
DatagramPacket ackPacket;
DatagramSocket sendSocket = null;
//DatagramSocket ackSocket = null;
static boolean ackReceived = true;
public FileSender(String zielRechner, String filePath) throws UnknownHostException, FileNotFoundException {
this.zielRechner = zielRechner;
this.filePath = filePath;
this.host = InetAddress.getByName(zielRechner);
this.file = new File(filePath);
fis = new FileInputStream(file);
}
public void sendFile() throws IOException {
while((readLength = fis.read(data)) != -1) {
if (sequenceNr == 1)
sequenceNr = 0;
else
sequenceNr = 1;
readLengthByte = intToBytes(readLength);
sequenceNrByte = intToBytes(sequenceNr);
for(int i=0; i<4; i++) {
header[8+i] = readLengthByte[i];
}
for(int i=0; i<4; i++) {
header[12+i] =sequenceNrByte[i];
}
int j=0;
for (int i=0; i<packet.length; i++) {
if (i < header.length)
packet[i] = header[i];
else {
packet[i] = data[j];
j++;
}
}
checksumCalculator.reset();
checksumCalculator.update(packet,8,8+readLength);
checksumByte = longToBytes(checksumCalculator.getValue());
for(int i=0; i < 8; i++) {
packet[i] = checksumByte[i];
}
dp = new DatagramPacket(packet, packet.length, host, port);
while(receivedSeqNr == sequenceNr && ackReceived) {
try {
ackReceived = false;
sendSocket = new DatagramSocket();
sendSocket.send(dp);
sendSocket.setSoTimeout(10000);
packetNr++;
System.out.println("Packet sent with seqNr: " + sequenceNr + " and length: " + bytesToInt(readLengthByte, 0) + " - PACKET NR: " + packetNr);
ackPacket = new DatagramPacket(ackBuffer, ackBuffer.length);
System.out.println("TEST!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
sendSocket.receive(ackPacket);
System.out.println("Receiving ACK!!");
ackReceived = true;
ackBuffer = ackPacket.getData();
receivedSeqNr = bytesToInt(ackBuffer,0);
System.out.println("got SequenceNr with receivedSeq-Nr: " + receivedSeqNr);
} catch (SocketTimeoutException e) {
e.printStackTrace();
break;
}
}
}
fis.close();
System.out.println("Transfer Completed Successfully!");
sendSocket.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 static void main(String[] args) throws IOException,ClassNotFoundException {
FileSender sender = new FileSender("localhost", "C:/Users/Kb/Desktop/Deepophile - Psychedelic Sessions.wav");
sender.sendFile();
}
}
这是服务器的代码:
package blatt7;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.zip.CRC32;
public class FileReceiver {
byte[] incomingBuffer;
DatagramPacket incomingPacket;
DatagramSocket receiveSocket;
DatagramPacket ackPacket;
int packetCounter = 0;
int dataLength;
int receivedSeqNr;
long calculatedChecksum;
long receivedChecksum;
CRC32 checksumCalculator = new CRC32();
byte[] dataLengthByte = new byte[4];
byte[] receivedSeqNrByte = new byte[4];
byte[] receivedChecksumByte = new byte[8];
byte[] ackArray;
public FileReceiver() throws SocketException {
incomingBuffer = new byte[1500];
incomingPacket = new DatagramPacket(incomingBuffer, incomingBuffer.length);
}
public void receive() throws IOException {
receiveSocket = new DatagramSocket(FileSender.port);
receiveSocket.setSoTimeout(10000);
System.out.println("Server socket created. Waiting for incoming data...");
while(true && FileSender.ackReceived)
{
receiveSocket.receive(incomingPacket);
packetCounter++;
for (int i=0; i <4; i++) {
dataLengthByte[i] = incomingBuffer[8+i];
}
dataLength = FileSender.bytesToInt(dataLengthByte,0);
checksumCalculator.reset();
checksumCalculator.update(incomingBuffer, 8, dataLength+8);
calculatedChecksum = checksumCalculator.getValue();
for (int i=0; i <4; i++) {
receivedSeqNrByte[i] = incomingBuffer[12+i];
}
receivedSeqNr = FileSender.bytesToInt(receivedSeqNrByte,0);
for (int i=0; i <8; i++) {
receivedChecksumByte[i] = incomingBuffer[i];
}
long receivedChecksum = FileSender.bytesToLong(receivedChecksumByte,0);
System.out.println("Got packet with checksum: " + receivedChecksum);
System.out.println("Server-calculated checksum: " + calculatedChecksum);
System.out.println("Got packet with seqNr: " + receivedSeqNr + " and length: " + dataLength);
if (calculatedChecksum != receivedChecksum) {
sendACK(receivedSeqNr);
System.out.println("Packet have erros(s)! It must be sent another time!");
}
else if(calculatedChecksum == receivedChecksum && receivedSeqNr == 1) {
sendACK(0);
System.out.println("SeqNr '0' sent");
}
else if (calculatedChecksum == receivedChecksum && receivedSeqNr == 0) {
sendACK(1);
System.out.println("SeqNr '1' sent");
}
}
}
public void sendACK(int seqNum) throws IOException {
byte[] ackArray = FileSender.intToBytes(seqNum);
ackPacket = new DatagramPacket(ackArray, ackArray.length, InetAddress.getByName("localhost"), FileSender.port);
receiveSocket.send(ackPacket);
}
public static void main(String[] args) throws IOException,ClassNotFoundException {
FileReceiver receiver = new FileReceiver();
receiver.receive();
}
}
您可以尝试执行它以查看问题出在哪里...因此,如果您知道如何解决此问题,请告诉我!
非常感谢!
有人能告诉我在哪里可以找到收到的文件吗?或者我应该如何更改我的代码,以便我选择在哪里保存它??
服务器如何使用自己的端口发送到客户端?您正在服务器端口上从服务器向客户端发送ACK,您应该从收到的数据包中获取客户端的UDP端口,并将数据发送到该端口。
编辑
在 SendACK 方法中的服务器中更改为:
ackPacket = new DatagramPacket(ackArray, ackArray.length, InetAddress.getByName("localhost"), incomingPacket.getPort());
现在通过运行来分析代码。
是的,有可能。你的问题是,当发送ACK数据报时,你有目标地址:端口错误。您应该从接收到的DatagramPacket中获取目标地址:端口,或者更简单的方法是将带有不同数据的数据报作为ACK数据报重用。
我正在使用React构建一个简单的项目,我希望它连接到一个数据库(mongodb Atlas)。但是,我只能使用Node连接到我的数据库。是否可以在同一个端口3000上运行两个节点和反应? 我还将Express与Node一起使用,因为我发现在制作具有相同navBar和页脚的新页面时使用ejs文件非常方便。 有没有可能把这三个人放在一个港口?
ServerSocket是来自Java.NET API的ServerSocket normal Socket是来自Java.NET API的Socket 是的,这里的ServerSocket是指建立连接后从ServerSocket.Accept返回的套接字
我编写UDP服务器,为NAT后面的客户端提供服务。 客户端将请求发送到公共IP和一些预定义的端口。服务器接收消息,创建(从池获取)线程并将消息传递给线程(处理程序)。 问题:我可以使用新的套接字(不同的端口)来发送响应,还是应该使用接收请求的相同端口(套接字)?
我正在尝试在具有不同日志目录的两个不同端口上启动kafka集群所需的两个zooKeer实例。但是当我尝试启动第二个zooKeer- D: \Kafka\Kafka\u 2.12-2.3.0-复制
问题内容: 我正在尝试在同一端口上启用tcp,http和websocket.io通信。我开始使用tcp服务器(在////行上方),它可以正常工作。然后,我运行了在websocket.io(位于////行下方的部分)上找到的echo服务器示例,它也可以正常工作。但是当我尝试将它们合并在一起时,tcp不再起作用。 因此,是否可以使用同一端口启用tcp,http和websockets?还是我必须在另一个
问题内容: 我已经安装了MySQL,甚至以用户身份登录那里。 但是当我尝试这样连接时: 都不行。不确定两者是否都应该工作,但其中至少有一个应该:) 如何确定端口确实是3306?有Linux命令可以以某种方式查看它吗?另外,是否有更正确的方法通过网址进行尝试? 问题答案: 要在端口上找到侦听器,请执行以下操作: 如果mysql确实在该端口上侦听,您应该看到一条类似于以下内容的行。 端口3306是My