- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在尝试发送一个 DatagramPacket,然后必须等待来自服务器的确认,以便我知道我是否必须重新发送相同的数据包或发送下一个数据包......
我在客户端使用相同的套接字,发送数据包并接收确认 (ack),在服务器端,另一个套接字用于接收数据包,然后发送致谢客户..
第一个问题是客户端正在发送数据包,服务器正在接收它,然后向客户端发送确认,但客户端在收到确认包时阻塞。
我正在制作一些 System.out.println 来确定问题出在哪里,但我找不到解决这个问题的方法。
第二个问题是服务器仍然总是在接收数据,并且不要等待客户端发送一些东西,我检查了因为我得到了那些行(比如“得到了长度为 xxx 的数据包”“ack sent with 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 数据报时目标地址:端口错误。您应该从接收到的 DatagramPacket 中获取目标地址:端口,或者更简单的只是重用具有不同数据的数据报作为 ACK 数据报。
关于java - 是否可以仅使用 1 个 UDPSocket 在同一端口上发送/接收?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14085606/
在将 UDPSocket 绑定(bind)到空闲端口号后,我正在尝试获取端口号。所以 udp_server = UDPSocket.newudp_server.bind('localhost', 0)
我正在尝试在 Tokio 中同时处理到达的 UDP 数据包。然而,以下 MWE 没有达到我的预期: extern crate futures; extern crate tokio_core; ext
我有一个运行 std::thread 的 NetworkDevice 类对所有传入的数据包进行排队。在执行此操作时,我还想在相同的 sf::UdpSocket 上发送数据包.我找不到任何关于 sf::
我是ruby新手,跟着《The Ruby Programming Language》这本书,我正在尝试学习一些ruby中的Socket,以下是我的简单服务器/客户端: ## server requir
使用 Rust 的 UdpSocket ,它似乎只有 send()、recv() 和 set_nonblocking(bool)。这是一组相当有限的功能,例如如果 recv() 总是阻塞直到收到数据包
我正在编写一个使用 UDP 发送和接收数据包的应用程序。然而,documentation of recv_from状态: If a message is too long to fit in the
我正在为我的 CS 类(class)开发一款原始的多人战舰游戏。我能够让它运行并通过 LAN 发送信息。为了测试此通信是否有效,我创建了一个带有监听器功能的循环,当确认已从另一台计算机的监听线程接收到
我正在尝试通过 UDPSocket 类向服务器发送一些十六进制数据。 require 'socket' socket = UDPSocket.new socket.send('230055', 0,
我的机器有两个以太网网络接口(interface)。 eno0 和 eno1。 eno0 是接入互联网的地方,eno1 有一个连接的以太网设备。我通过 Link-Local Address 方法得到它
std::old_io::net::udp::UdpSocket已替换为 std::net::UdpSocket , 和 fn set_timeout(&mut self, timeout_ms: O
我想使用 udp 协议(protocol)发送消息。我有一个像这样的网址这个:http://torrent.ubuntu.com:6969/announce。 但是在文档和所有示例中,我看到方法 bi
我正在处理 simple example用于创建 rust udp 客户端/服务器应用程序。但是当尝试使用 send_to 或 recv_from 方法时,我收到以下错误: [E0599] 没有名为
我在使用 Rust 试验 BitTorrent 跟踪器协议(protocol)时遇到了这个问题。 这个应该使用 UDP 套接字发送一些数据的简单程序失败了: use std::collections:
let addr = "239.255.255.250:1982"; let socket = UdpSocket::bind(addr).unwrap(); let message = "some
我正在尝试做相当于 this piece of Ruby 的事情: def color=(color) @color = color any_bar = UDPSocket.new any
我正在尝试发送一个 DatagramPacket,然后必须等待来自服务器的确认,以便我知道我是否必须重新发送相同的数据包或发送下一个数据包...... 我在客户端使用相同的套接字,发送数据包并接收确认
这个问题在这里已经有了答案: Reading from TcpStream results in empty buffer (1 个回答) UdpSocket.recv_from fails with
我刚刚解决了基础架构中的一个延迟问题,该问题是由于此处的代码片段在每次运行代码时触发了对 getaddrinfo 的调用而触发的: sock = UDPSocket.open sock.send("#
我正在使用 mio::udp::UdpSocket 接收对来自客户端的请求的响应。看起来我在触发事件上收到了部分 UDP 数据包。我不确定这是否是 mio 库中的错误。 我已经尝试过 PollOpt:
Editor's note: This code example is from a version of Rust prior to 1.0 and is not valid Rust 1.0 co
我是一名优秀的程序员,十分优秀!