2012-12-20 152 views
0

我试图实现一个服务器和客户端,它们都以不同的顺序发送和接收数据报。我正在尝试以下方式,但客户端的数据报不会被发送/接收。从服务器和客户端以UDP发送和接收C

这里的客户端:

#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);  
} 
+0

而且,你的问题是......(顺便说一句,从这里开始:http://www.linuxhowtos.org/C_C++/socket.htm) – KevinDTimm

+0

如果这是Linux - strace显示的是什么? – pm100

+1

顺便说一句,您的服务器端口#是0,但它设置在客户端的命令行上。 – KevinDTimm

回答

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"); 
相关问题