【问题标题】:Send and receive in UDP from server and client in C在 C 中从服务器和客户端以 UDP 发送和接收
【发布时间】:2012-12-21 07:26:34
【问题描述】:

我正在尝试实现一个服务器和一个客户端,它们都发送和接收(以不同的顺序)数据报。我正在尝试以下方式,但未发送/接收来自客户端的数据报。

这里是客户:

#include <sys/socket.h>
#include<netdb.h>
#include <netinet/in.h>
#include <stdio.h>

#define DATA "Este es el mensaje ...."

int main(int argc, char *argv[])
{
 int sock, lon2;
 struct sockaddr_in name, name2;
 struct hostent *hp;
 char buf[1024];

 sock=socket(PF_INET,SOCK_DGRAM,0);

 if (sock<0)
    {
     perror("Abriendo socket de datagramas");
     exit(1);
    }


 /*devuelve una estructura hostent para el host especificado en argv[1]*/
 /*para obtener la direccion IP a partir del nombre de la maquina*/
 hp=gethostbyname(argv[1]);

 if (hp == 0)
    {
     fprintf(stderr,"%s: host desconocido",argv[1]);
     exit(2);
    }

 /*Copiamos en la estructura name la direccion del ordenador al que */
 /*vamos a conectarnos.*/
 memcpy((char *)&name.sin_addr, (char *)hp->h_addr, hp->h_length);

 name.sin_family = AF_INET;
 name.sin_port   = htons(atoi(argv[2]));

 if (sendto(sock,DATA,strlen(DATA)+1,0,(struct sockaddr *)&name,sizeof(name))<0)
    perror("Enviando un datagrama");



 if (read(sock,buf,1024)<0)
    perror("Recibiendo el datagrama");   

 printf("-->%s\n",buf);   
 close(sock);
 exit(0);       
}

这里是服务器:

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#define DATA "Este es el mensaje ....bvbvbvbv"
int main()
{
 int sock, length, lon2;
 struct sockaddr_in name;
 char buf[1024];

 sock=socket(PF_INET,SOCK_DGRAM,0);

 if (sock<0)
    {
     perror("Abriendo socket de datagramas");
     exit(1);
    }

 /*Formato de la direccion*/
 name.sin_family=AF_INET;   

 /*Direccion IP, INADDR_ANY -> que cuando se use bind para asociar una*/
 /*direccion a un socket, la direccion IP es la de la maquina donde esta*/
 /*ejecutandose el programa.*/                        
 name.sin_addr.s_addr=htonl(INADDR_ANY);

 /*0-> cuando se utilice bind(), el puerto que se va a asociar al socket es */
 /*uno libre asignado por el SO.*/
 name.sin_port=htons(0);

 if (bind(sock,(struct sockaddr *)&name, sizeof(name))<0)
    {
     perror("Asociando nombre al socket");
     exit(1);
    } 

 /*Hasta despues del bind no sabremos la direccion del socket asignada.*/
 /*=> usar getsockname()*/    

 length=sizeof(name);

 /*sock   = socket del que queremos saber la direccion*/
 /*name   = estructura en la que se va a dejar la direccion*/
 /*length = tamano ocupado por la estructura.*/ 
 if (getsockname(sock,(struct sockaddr *)&name,&length)<0)
    {
     perror("Averiguando el nombre del socket");
     exit(1);
    }   

/*Imprimimos el puerto para que el emisor mande a ese puerto.*/    
 printf("puerto del socket -->%d\n", ntohs(name.sin_port));

 if (recvfrom(sock,buf,1024,0,(struct sockaddr *)NULL,&lon2)<0)
    perror("Recibiendo el datagrama"); 

 printf("-->%s\n",buf);

 if (sendto(sock,DATA,strlen(DATA)+1,0,(struct sockaddr *)&name,sizeof(name))<0)
    perror("Enviando un datagrama");

 close(sock);
 exit(0);       
}

【问题讨论】:

  • 而且,你的问题是......(顺便说一句,从这里开始:linuxhowtos.org/C_C++/socket.htm
  • 如果这是 linux - strace 会显示什么?
  • 顺便说一句,你的服务器端口号是 0 但它是在客户端的命令行上设置的。
  • 它应该可以工作。来自服务器的数据报在客户端接收并显示在 promt 中。但不是以另一种方式。它应该可以工作,因为我正在接收的同一个套接字中发送......
  • @saimonx,看起来您的服务器正在将收到的数据包发送回自己(name 指向本地套接字端点)。

标签: c sockets datagram


【解决方案1】:

您的客户端代码很好,但您确实应该“绑定”客户端套接字。 (指定 sin_port=0 可以让操作系统选择一个随机端口号)。我认为如果套接字没有被“绑定”到一个端口并且没有真正监听一个端口,一些操作系统会为每个 sendto 选择一个随机端口。我可能会将其与其他内容混淆,但无论如何,为客户端套接字调用 bind 是一件好事。绑定到端口 0 至少会使套接字在它发送数据的同一端口上侦听。

sockaddr_in localAddr = {}; // zero's out sin_port and sets sin_addr to INADDR_ANY (0)
int result;

localAddr.sin_family = PF_INET;
sock=socket(PF_INET,SOCK_DGRAM,0);
if (sock < 0) {perror("socket error"); exit(1);}

result = bind(sock, (sockaddr*)&localAddr, sizeof(localAddr));
if (result < 0) {perror("bind error"); exit(1);}

但这不是您唯一的问题。在您的服务器代码中:

if (recvfrom(sock,buf,1024,0,(struct sockaddr *)NULL,&lon2)<0)
    perror("Recibiendo el datagrama"); 

 printf("-->%s\n",buf);

if (sendto(sock,DATA,strlen(DATA)+1,0,(struct sockaddr *)&name,sizeof(name))<0)
    perror("Enviando un datagrama");

您实际上并没有将数据发送回接收数据的远程 IP/端口。这更有可能奏效:

sockaddr_in remoteClient = {};
socklen_t remoteClientSize = sizeof(remoteClient);

if (recvfrom(sock,buf,1024,0,(struct sockaddr *)&remoteClient,&remoteClientSize)<0)
    perror("Recibiendo el datagrama"); 

 printf("-->%s\n",buf);

if (sendto(sock,DATA,strlen(DATA)+1,0,(struct sockaddr *)&remoteClient,remoteClientSize)<0)
    perror("Enviando un datagrama");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-10
    • 1970-01-01
    • 1970-01-01
    • 2017-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多