我正在尝试实现一个服务器和一个客户端,它们发送和接收(以不同的顺序)数据报。我正在尝试以下方式,但不发送/接收来自客户端的数据报。
客户端:
#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 :(得分: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");