首页 > 解决方案 > “已连接” UDP 套接字,双向通信?

问题描述

如何在连接的 UDP 套接字上实现 2 路通信?

我可以从客户端向服务器发送消息,但无法从服务器获取消息。这是我的代码。我认为这个问题一定是在服务器端,但我不知道如何解决这个问题。我故意删除了错误检查,只是为了在 SO 上发布并保持我的帖子简短。我没有收到任何错误。

我可以使用未连接的UDP 套接字运行该程序,但不能使用已连接的套接字。

服务器.c

#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <errno.h>

int main()
{
  int sockfd;
  struct sockaddr_in me;
  char buffer[1024];

  sockfd = socket(AF_INET, SOCK_DGRAM, 0);

  memset(&me, '\0', sizeof(me));
  me.sin_family = AF_INET;
  me.sin_port = htons(8080);
  me.sin_addr.s_addr = inet_addr("127.0.0.1");

  bind(sockfd, (struct sockaddr *)&me, sizeof(me));

  recv(sockfd, buffer, 1024, 0);
  printf("[+]Data Received: %s\n", buffer);

  strcpy(buffer, "Hello Client\n");
  send(sockfd, buffer, 1024, 0);
  printf("[+]Data Send: %s\n", buffer);

  return 0;
}

客户端.c

#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <errno.h>

int main()
{
  int sockfd;
  struct sockaddr_in other;
  char buffer[1024];

  sockfd = socket(AF_INET, SOCK_DGRAM, 0);

  memset(&other, '\0', sizeof(other));
  other.sin_family = AF_INET;
  other.sin_port = htons(8080);
  other.sin_addr.s_addr = inet_addr("127.0.0.1");

  connect(sockfd, (struct sockaddr *)&other, sizeof(other));

  strcpy(buffer, "Hello Server\n");
  send(sockfd, buffer, 1024, 0);
  printf("[+]Data Send: %s\n", buffer);

  recv(sockfd, buffer, 1024, 0);
  printf("[+]Data Received: %s\n", buffer);

  return 0;
}

服务器输出

[+]Data Received: Hello Server
[+]Data Send: Hello Client

客户端的输出

[+]Data Send: Hello Server
// Here it does not receive the message sent by server.

标签: csocketsnetworkingnetwork-programmingudp

解决方案


On linux, straceing the executable, the server send does say this:

sendto(3, "Hello Client\n\0\0\0\310$\220\4J\177\0\0\0\0\0\0\0\0\0\0"...,
       1024, 0, NULL, 0) = -1 EDESTADDRREQ (Destination address required)

i.e. the server socket indeed does not know the address it needs to send to. Any UDP socket must make the other end of the socket known by either connecting, or providing the destination socket address in sendto. connect on an UDP socket means just setting a default address for send.


To connect the socket on the "server" side, with an unknown party you should use recvfrom to find out the socket address of the sending party - then you can connect using this address or continue using sendto. With sendto the same socket can communicate with many different parties concurrently.


The TCP server/client sockets are a different case, because listen/accept on the server side returns a new connected socket that is distinct from the original server socket.


推荐阅读