我运行了一个模拟测试,以了解UDP通信面临的问题。
我有一个主机,其中有4个UDP客户机正在运行,每个客户机都有自己的线程(T1、T2、T3和T4)。T1和T2共享一个名为socket的DatagramSocket对象,而T3和T4共享一个名为socket2的DatagramSocket对象。
T1和T2正在发送和接收来自IP(例如)udpServer1的UDP服务器的回波,而T3和T4正在与udpServer2通信。
当并行运行线程时,我能够同步共享相同DatagramSocket和Runnable对象的T1和T2。然而,当尝试运行使用不同DatagramSocket和Runnable对象的T1和T3时,T3总是在SocketTimeoutExc0019下失败,但是T1可以毫无问题地发送和接收数据包。
总之:
>
并行运行T1和T2(或T3和T4),共享相同的DatagramSocket和Runnable对象--
并行运行T1和T3,每个都使用自己的DatagramSocket和Runnable对象--
为什么T3在自己的DatagramSocket上并在自己的线程上运行时,仍然会获得SocketTimeoutExcsion?我到底做错了什么?
任何帮助都非常感谢。谢谢。
@Test
public void sendRemoteTest() throws InterruptedException, IOException {
DatagramSocket socket = new DatagramSocket(9987, InetAddress.getByName(localMachineIp));
DatagramSocket socket2 = new DatagramSocket(9988, InetAddress.getByName(localMachineIp));
UdpClientRunnable runnable = new UdpClientRunnable(socket, 1);
UdpClientRunnable runnable2 = new UdpClientRunnable(socket2, 1);
Thread t1 = new Thread(runnable);
t1.setName("T1");
Thread t2 = new Thread(runnable);
t2.setName("T2");
Thread t3 = new Thread(runnable2);
t3.setName("T3");
Thread t4 = new Thread(runnable2);
t4.setName("T4");
t1.start();
t2.start();
t3.start();
t4.start();
Thread.sleep(10000);
t1.join();
t2.join();
t3.join();
t4.join();
}
private byte toByte(int num) {
return (byte) ((byte) (0xFF) & num);
}
public class UdpClientRunnable implements Runnable {
private DatagramSocket socket;
private long delayMillis;
private byte[] dataToSend;
public UdpClientRunnable(DatagramSocket socket, long delayMilis) {
this.socket = socket;
this.delayMillis = delayMilis;
}
@Override
public synchronized void run() {
byte[] data1 = new byte[] { toByte(0x01), toByte(0x01), toByte(0x01),
toByte(0x01), toByte(0x01) };
byte[] data2 = new byte[] { toByte(0x02), toByte(0x02), toByte(0x02),
toByte(0x02), toByte(0x02) };
byte[] data3 = new byte[] { toByte(0x03), toByte(0x03), toByte(0x03),
toByte(0x03), toByte(0x03) };
byte[] data4 = new byte[] { toByte(0x04), toByte(0x04), toByte(0x04),
toByte(0x04), toByte(0x04) };
String targetIp = "";
String name = Thread.currentThread().getName();
if (name.contains("T1")) {
dataToSend = data1;
targetIp = udpServer1;
}
else if (name.contains("T2")){
dataToSend = data2;
targetIp = udpServer1;
}
else if (name.contains("T3")) {
dataToSend = data3;
targetIp = udpServer2;
}
else {
dataToSend = data4;
targetIp = udpServer2;
}
int count = 0;
while (count < 250) {
try {
sendAndReceive(targetIp, name, count, dataToSend);
Thread.sleep(delayMillis);
}
catch (IOException | InterruptedException e) {
System.out.println(e + ": " + name + ", iter: " + count);
}
finally {
++count;
}
}
}
private synchronized void sendAndReceive(String targetIp, String threadName, int count, byte[] dataToSend) throws IOException, UnknownHostException, SocketException {
byte[] rcvData = new byte[5];
DatagramPacket rcvPacket = new DatagramPacket(rcvData, rcvData.length);
socket.send(new DatagramPacket(dataToSend, 5, InetAddress.getByName(targetIp), 9999));
socket.setSoTimeout(2000);
rcvPacket = new DatagramPacket(rcvData, rcvData.length);
socket.receive(rcvPacket);
printData(threadName, count, rcvData);
if (threadName.contains("T1")) {
Assert.assertArrayEquals(new byte[] { toByte(0x01), toByte(0x01), toByte(0x01),
toByte(0x01), toByte(0x01) }, rcvData);
}
else if (threadName.contains("T2")){
Assert.assertArrayEquals(new byte[] { toByte(0x02), toByte(0x02), toByte(0x02),
toByte(0x02), toByte(0x02) }, rcvData);
}
else if (threadName.contains("T3")){
Assert.assertArrayEquals(new byte[] { toByte(0x03), toByte(0x03), toByte(0x03),
toByte(0x03), toByte(0x03) }, rcvData);
}
else if (threadName.contains("T4")){
Assert.assertArrayEquals(new byte[] { toByte(0x04), toByte(0x04), toByte(0x04),
toByte(0x04), toByte(0x04) }, rcvData);
}
}
private void printData(String name, int count, byte[] rcvData) {
String prefix = "";
for (int i = 0; i < rcvData.length; i++) {
prefix = (i == 0) ? (name + " iter " + count + ": ") : "";
System.out.print(prefix + Integer.toHexString((byte) ((byte) (0xFF) & rcvData[i])) + " ");
}
System.out.println();
}
}
查看代码,有两台服务器位于两台不同的机器上,我假定侦听的是同一端口999。因此,我认为问题可能在于服务器代码。当你回复客户时,你是这样做的吗
byte[] rcvData = new byte[5];
DatagramPacket rcvPacket = new DatagramPacket(rcvData, rcvData.length);
socket.receive(rcvPacket);
DatagramPacket sendPacket = new DatagramPacket(rcvPacket.getData(), rcvPacket.getLength(), rcvPacket.getAddress(), rcvPacket.getPort()); // note that here we need to use the received packet information on where to send the response back
socket.send(sendPacket);
很少有其他评论
UDP协议是一个简单的面向数据报的传输层协议,它是一种不可靠数据报协议。由于缺乏可靠性且属于非连接导向协定,UDP应用一般必须允许一定量的丢包和出错。 Chrome提供sockets.udp接口使Chrome应用可以进行UDP通信。要使用sockets.udp接口需要在sockets域中声明udp权限: "sockets": { "udp": { "send": ["192
主要内容:本节引言:,1.服务端实现步骤:,2.客户端实现步骤:,本节小结:本节引言: 本节给大家带来Socket的最后一节:基于UDP协议的Socket通信,在第一节中我们已经详细地 比较了两者的区别,TCP和UDP最大的区别在于是否需要客户端与服务端建立连接后才能进行 数据传输,如果你学了前两节TCP的,传输前先开服务端,accept,等客户端接入,然后获得 客户端socket然后进行IO操作,而UDP则不用,UDP以数据报作为数据的传输载体,在进行传输时 首先要把传
我们已经讲解了物理层、连接层和网络层。最开始的连接层协议种类繁多(Ethernet、Wifi、ARP等等)。到了网络层,我们只剩下一个IP协议(IPv4和IPv6是替代关系)。进入到传输层(transport layer),协议的种类又开始繁多起来(比如TCP、UDP、SCTP等)。这就好像下面的大树,根部(连接层)分叉很多,然后统一到一个树干(网络层),到了树冠(传输层)部分又开始开始分叉,而每
如何定制协议 实际上制定自己的协议是比较简单的事情。简单的协议一般包含两部分: 区分数据边界的标识 数据格式定义 一个例子 协议定义 这里假设区分数据边界的标识为换行符”\n”(注意请求数据本身内部不能包含换行符),数据格式为Json,例如下面是一个符合这个规则的请求包。 {"type":"message","content":"hello"} 注意上面的请求数据末尾有一个换行字符(在PHP中
本文向大家介绍TCP、UDP 协议的区别?相关面试题,主要包含被问及TCP、UDP 协议的区别?时的应答技巧和注意事项,需要的朋友参考一下 tcp 和 udp 是 OSI 模型中的运输层中的协议。tcp 提供可靠的通信传输,而 udp 则常被用于让广播和细节控制交给应用的通信传输。 两者的区别大致如下: tcp 面向连接,udp 面向非连接即发送数据前不需要建立链接; tcp 提供可靠的服务(数据
UDP 简介 UDP 是一个简单的传输层协议。和 TCP 相比,UDP 有下面几个显著特性: UDP 缺乏可靠性。UDP 本身不提供确认,序列号,超时重传等机制。UDP 数据报可能在网络中被复制,被重新排序。即 UDP 不保证数据报会到达其最终目的地,也不保证各个数据报的先后顺序,也不保证每个数据报只到达一次 UDP 数据报是有长度的。每个 UDP 数据报都有长度,如果一个数据报正确地到达目的地,