2012-12-20 252 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"); 
相關問題