2016-03-10 47 views
-1

我需要通过udp连接两个程序。这是工作的方式是两个程序都是udp服务器,并且它们在两个端口上发送和接收,如下所示:如何强制udp服务器接收到的udp客户端套接字绑定到特定的客户端端口

programA在端口20037上侦听并在端口20038上发送。 programB侦听端口20038并在端口20037上发送

programA和programB都运行在同一台计算机上。

programA已经写好了,它看起来像上面那样绑定了它的套接字。即发送端口= 20038和监听端口= 20037.

我已经写了一个udp程序作为programB。

我的程序B将服务器套接字绑定到端口20038,这是正确的。

但当programB收到programA消息,客户socket似乎绑定到一些随机端口,如端口10690.但我需要它绑定到端口20037.

使用的协议,需要发送收到消息时返回简单的确认消息。

我的代码如下所示:

struct sockaddr_in client; 
char buffer[BUFFER_SIZE]; 
/* Loop and get data from clients */ 
while (1) 
{ 
    int client_length = (int)sizeof(struct sockaddr_in); 

    /* Receive bytes from client */ 
int bytes_received = recvfrom(sd, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&client, &client_length); 
if (bytes_received < 0) 
{ 
     fprintf(stderr, "Could not receive datagram.\n"); 
     closesocket(sd); 
     WSACleanup(); 
     exit(0); 
    } 

    printf("%u bytes received from client on port %u\n", bytes_received, client.sin_port); 
    SendAck(); 
} 

而且SendAck()是这样的:

void udpserver::SendAck() { 

    unsigned char acker[] = { SOM, ACK }; 
    int length = sizeof(acker)/sizeof(acker[0]); 

    int client_length = (int)sizeof(struct sockaddr_in); 
    if (sendto(sd, (const char*)acker, length, 0, (struct sockaddr *)&client, client_length) == -1) 
    { 
     fprintf(stderr, "Error transmitting data.\n"); 
     closesocket(sd); 
     WSACleanup(); 
     exit(0); 
    } 
    else 
     printf("successfully sent ack to client\n"); 
} 

我认为收到的将是20037客户端套接字的端口号,但它是一个随机数。我可以强制客户端套接字绑定到端口20037?因为ack消息必须发送到端口20037.

而且我无法更改此设计。 ProgramA将始终绑定到监听端口20037,并通过将其客户端端口绑定到20038来发送。我可以自由地执行programB所需的任何操作。

回答

0

recvfrom()报告说,接收到的数据包被发送远程IP /端口从。 ProgramA从端口20038. SendAck()使用由recvfrom()提供的客户端的信息,这意味着主叫ACK发送sendto()数据被发送到端口20038,而不是端口20037.

这是不寻常的一个UDP系统发送答复到一个不同于发送端口的端口。但是,这样吧。你将不得不告诉sendto()要发送到哪个端口。

您也没有正确记录发件人的端口。网络字节顺序表示client.sin_port。在登录时使用ntohs()将其更改为主机字节顺序。如果没有这样做,将会导致你所看到的随机号码。

试试这个:

struct sockaddr_in client; 
char buffer[BUFFER_SIZE]; 

/* Loop and get data from clients */ 
while (1) 
{ 
    int client_length = (int)sizeof(struct sockaddr_in); 

    /* Receive bytes from client */ 
    int bytes_received = recvfrom(sd, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&client, &client_length); 
    if (bytes_received < 0) 
    { 
     fprintf(stderr, "Could not receive datagram.\n"); 
     closesocket(sd); 
     WSACleanup(); 
     exit(0); 
    } 

    printf("%u bytes received from client at %s on port %u\n", bytes_received, inet_ntoa(client.sin_addr), ntohs(client.sin_port)); 

    SendAck(&client); 
} 

void udpserver::SendAck(struct sockaddr_in *client) 
{ 
    struct sockaddr_in receiver; 

    memcpy(&receiver, client, sizeof(struct sockaddr_in)); 
    receiver.sin_port = htons(20037); 

    unsigned char acker[] = { SOM, ACK }; 
    int length = sizeof(acker)/sizeof(acker[0]); 

    if (sendto(sd, (const char*)acker, length, 0, (struct sockaddr *)&receiver, sizeof(struct sockaddr_in)) == -1) 
    { 
     fprintf(stderr, "Error transmitting data.\n"); 
     closesocket(sd); 
     WSACleanup(); 
     exit(0); 
    } 
    else 
     printf("successfully sent ack to client at %s on port %d\n", inet_ntoa(receiver.sin_addr), ntohs(receiver.sin_port)); 
} 
0

绑定插座要作为出站口口:

client.sin_port = htons(20037); 

,然后发送:

sendto(sd, (const char*) acker, length, 0, 
     (struct sockaddr*) &client, client_length);