Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ UDP中的客户端服务器回显程序陷入死锁_C++_Sockets_Udp - Fatal编程技术网

C++ UDP中的客户端服务器回显程序陷入死锁

C++ UDP中的客户端服务器回显程序陷入死锁,c++,sockets,udp,C++,Sockets,Udp,以下是UDP客户端服务器回显程序的客户端代码: ret_val = sendmmsg(socket_id, msgs, no_of_packets, 0); //I send message to the server if(ret_val == -1) std::cerr << "Message sending failed.\n"; else{ cout << ret_val << " messages sent\n"; /**********

以下是UDP客户端服务器回显程序的客户端代码:

ret_val = sendmmsg(socket_id, msgs, no_of_packets, 0);
//I send message to the server
if(ret_val == -1)
  std::cerr << "Message sending failed.\n";
else{
  cout << ret_val << " messages sent\n";
  /************************************************************************/
  char buffers[no_of_packets][packet_size + 1];
  msgs = new struct mmsghdr[no_of_packets];
  iovecs = new struct iovec[no_of_packets];
  memset(msgs, 0, sizeof(msgs));
  memset(iovecs, 0, sizeof(iovecs));
  for(int i = 0;i < no_of_packets;i++){
    iovecs[i].iov_base = buffers[i];
    iovecs[i].iov_len = packet_size;
    msgs[i].msg_hdr.msg_iov = &iovecs[i];
    msgs[i].msg_hdr.msg_iovlen = 1;
  }
  //and receive the packet here, but the program hangs here
  ret_val = recvmmsg(socket_id, msgs, no_of_packets, 0, NULL);
ret_val=sendmmsg(socket_id,msgs,无数据包,0);
//我向服务器发送消息
如果(返回值==-1)

服务器代码中的这一行看起来可疑:

if(connect(socket_id, (struct sockaddr *) &server_addr, sizeof(server_addr)) == -1)
什么是服务器地址?它肯定不是先前调用
recvmmsg
返回的任何数据包的源地址

只需删除
connect
呼叫即可

我可以写更多,但是您使用
recvmmsg
sendmmsg
而不是
recvfrom
sendto
有什么特别的原因吗

下面是使用udp套接字实现echo服务器的一种简单得多的方法:

const int MAX_UDP_MESSAGE_SIZE = 65535
unsigned char message[MAX_UDP_MESSAGE_SIZE+1];
int rcvReslt, sndResult;
sockaddr_in addr = {};
socklen_t addrLength = sizeof(addr);

rcvResult = recvfrom(socket_id, message, MAX_UDP_MESSAGE_SIZE, 0, (sockaddr*)&addr, &addrLength);
if (rcvResult > 0)
{
    message[rcvResult] = 0; // null terminate the message
    printf("Trip %d : %s\n", trip, message);

    // echo back
    sndResult = sendto(socket_id, message, rcvResult, 0, (sockaddr*)&addr, addrLength);
}
else
{
    int error_code = errno;
    printf("Error: %d\n", error_code);
}

很明显,你接错了目标。你根本不需要连接
recvfromsg()
两者都返回源IP:port。把它送回同一个地方

server\u addr
是server\u addr
中的
struct sockaddr\u,我在前面的
bind
系统调用中使用了它,我需要执行
connect
,因为没有它,
sendmmsg
调用失败并返回-1,我使用这些调用是因为我需要使用一个系统调用发送多个数据报@selbie
sendmmsg
没有失败,因为您没有调用
connect
sendmmsg
由于其他原因失败。很可能是因为您的代码没有正确填写每个回复的msg_hdr结构。(调用
connect
可能会使缺少有效的发送地址成为一种有效的情况,但您可能要做的只是发送回您自己。)当套接字函数返回-1时,您应该打印
errno
的值,因为这将告诉您实际的问题。这里没有套接字函数返回-1,为什么我只能在使用
connect
呼叫后才能发送,如果您看到
man 2 sendmmsg
,您可以在给出的示例程序中看到他们使用了
connect
@selbieJarvis,在UDP套接字上进行
连接
并不常见。特别是在服务器端,您可以从不同地址的客户端接收套接字。我已经更新了我的答案,以提供一种更简单的方法来实现带有UDP套接字的echo服务器。根据您的要求,以及我之前为您所做的回答,我怀疑您认为UDP消息可以成批发送和接收。sendmmsg(逻辑上)所做的就是在循环中调用
sendto
。类似地,recvmmsg所做的就是查看接收队列以查看是否有其他消息可用。我不明白,如果我删除
connect
系统调用,我将无法在服务器端使用
sendmmsg()
系统调用。不,我不能。因为没有connect系统调用,
sendmmsg
无法工作。检查
man 2 sendmmsg
。我会重复
recvfrom()
可以返回源地址
sendmsg()
可以提供目标地址。
recvfrom()
返回的源地址正是通过
sendto()
进行回复所需的目标地址。或者分别是
recvmsg()/sendmsg()
。您不需要
connect()
。见男子2。
const int MAX_UDP_MESSAGE_SIZE = 65535
unsigned char message[MAX_UDP_MESSAGE_SIZE+1];
int rcvReslt, sndResult;
sockaddr_in addr = {};
socklen_t addrLength = sizeof(addr);

rcvResult = recvfrom(socket_id, message, MAX_UDP_MESSAGE_SIZE, 0, (sockaddr*)&addr, &addrLength);
if (rcvResult > 0)
{
    message[rcvResult] = 0; // null terminate the message
    printf("Trip %d : %s\n", trip, message);

    // echo back
    sndResult = sendto(socket_id, message, rcvResult, 0, (sockaddr*)&addr, addrLength);
}
else
{
    int error_code = errno;
    printf("Error: %d\n", error_code);
}