Requirement:
Implementation:
为了实现这一点,我使用了队列/线程池机制。最初,我创建一个固定数量线程的池,并有一个队列datastructure来存储客户机地址。这个队列在所有线程之间共享,因此我使用“互斥”来锁定/解锁这个队列。在主服务器线程中,我创建一个套接字,将其绑定到全局端口/地址,然后在“recvfrom”调用上阻止服务器。任何希望与服务器通信的客户端都会向侦听全局端口地址的主线程服务器发送“HI”消息。主服务器线程在接收到这个“hi”数据报时,将客户机的sockaddr结构推送到队列中,并返回到“recvfrom”调用上的block以接受其他客户机。
在队列上获得锁的任何池线程,弹出客户机的地址,并开始自己处理这个客户机。也就是说,池线程现在将创建一个套接字,将它绑定到与全局端口不同的端口,并使用它弹出的客户端地址将这个端口地址发送给客户端。在客户端,在发送“hi”消息后,它阻止“recvfrom”调用,一旦它从服务器(具有不同的端口)接收到消息,它就存储这个端口/地址,从那时起,它只使用池服务器线程发送的这个新端口与服务器通信。
Clarification needed:
我在许多堆栈溢出问题中注意到,在多线程UDP服务器中,单个套接字总是足够的,但根据我的要求,我认为我需要多个UDP套接字,每个套接字满足一个客户机。请提供我的建议,我的方法线程UDP服务器为我的要求
编辑:改进了设计
感谢您对我设计的所有评论和讨论。在掌握了您关于单套接字连接和上下文切换的所有观点之后,我想到了一个改进的设计。请对我的改进设计提供反馈
在这个实现中,我将只使用一个绑定到全局已知端口地址的全局UDP套接字。就像前面一样,我最初将创建固定数量的线程,比如说5个线程。然后对所有线程中的单个套接字执行recvfrom()。无论哪个线程首先接收到数据报,都能够从该数据报中知道三件事:
一旦socket足够了,因为您可以在每次接收数据包时通过使用其源地址(src_addr)调用recvfrom来识别客户机:
recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
现在,这个解决方案有一个单一的接收点。这意味着服务器必须接收数据,然后将其传递给应该执行该过程的线程。这降低了单套接字解决方案的并行性,因为您只使用一个端口。
编辑:
我是个新手,如果你能给我建议的话,请告诉我。我有一个向客户端广播消息的服务器。然后客户端将回复发送回服务器。我想用单独的线程处理每个回复。每个回复都有mesage id和thread id。我如何用来自所有线程的信息填充一些结构,然后读取它 也从我的代码,它是正确地创建线程,而还是它存在某种方式来创建线程,只是如果我得到客户端的回复? 我是从正确的理解开始的吗? 非常感谢。
这是我的客户端和服务器的代码。 class Client1{Client1(int no){try{String message;message=“Hello this is client”+no;byte[]b=message.getBytes();DatagramPacket dp=new DatagramPacket(b,b length,inetAddress.getLocalHost()
我有两个线程,一个在一个套接字上监听并添加到队列中,另一个从队列中减去并提交处理。第二个线程在队列为空时Hibernate。这个睡眠不知怎么会影响第一个线程,也就是说,如果您移除睡眠或使它变大,那么第一个线程的socket.receive中的延迟就会增加。如果我保持尽可能低的睡眠,它会变得更好,但不是完美的。我做错了什么?
问题内容: 服务器和客户端使用我自己的协议(类似于XMPP)进行通信。我应该实现聊天应用程序。因此,当一个用户写String时,应该立即将其通过服务器发送给其他客户端。我在服务器上有sendToAll方法。但是用户只有在按Enter时才能看到其他用户的消息。 用户如何在不按Enter键的情况下接收消息? 这是我的客户: 和带有ServerThread的服务器。 ServerThread。 问题答案
服务器和客户端使用我自己的协议进行通信,看起来像XMPP。我应该实现聊天应用。因此,当一个用户编写String时,它应该立即通过服务器发送给其他客户端。我在服务器上有sendToAll方法。但用户只有在按下回车键时才能看到其他用户的消息。用户如何在不按回车键的情况下接收消息? 这是我的客户: 以及带有ServerThread的服务器。 服务器线程。