[英]echo server not responding udp
我正在尝试实现回显客户端。 客户端使用sendto()发送消息,而服务器正在接收n显示消息。 但是服务器没有发送消息(回送)。 这是服务器和客户端的代码。 谁能帮我这个?
服务器:
char msg[100]="";
int conn_sock,n;
struct sockaddr_in server_addr,client_addr;
conn_sock=socket(AF_INET,SOCK_DGRAM,0);
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons(1234);
server_addr.sin_addr.s_addr=inet_addr("127.0.0.1");
err=bind(conn_sock, (struct sockaddr *)&server_addr,sizeof(server_addr));
n=recvfrom(conn_sock,msg,sizeof(msg),0,(struct sockaddr *)&client_addr,(socklen_t *)&client_addr);
n=sendto(conn_sock,msg,sizeof(msg),0,(struct sockaddr *)&client_addr,sizeof(client_addr));
在recvfrom中,n的值是字节数。 但在sendto()中,n的值为-1
客户:
char msg[100];
int conn_sock,n,err;
struct sockaddr_in server_addr;
conn_sock=socket(AF_INET,SOCK_DGRAM,0);
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons(1234);
server_addr.sin_addr.s_addr=inet_addr("127.0.0.1");
cin>>msg;
n=sendto(conn_sock,msg,strlen(msg),0,(struct sockaddr *)&server_addr,sizeof(server_addr));
n=recvfrom(conn_sock, msg, 15, 0, (struct sockaddr*) &server_addr,(socklen_t *)&server_addr);
recvfrom()未从服务器接收任何数据。
这两行都是错误的:
// In the server
n=recvfrom(conn_sock,msg,sizeof(msg),0,(struct sockaddr *)&client_addr,(socklen_t *)&client_addr);
// In the client
n=recvfrom(conn_sock, msg, 15, 0, (struct sockaddr*) &server_addr,(socklen_t *)&server_addr);
recvfrom()
的最后两个参数应该指向两个单独的变量。 其中一个接收对方的网络地址,另一个接收该网络地址的长度。 将相同的指针值传递给两个指针意味着地址长度将覆盖地址数据的前几个字节,从而破坏地址数据并导致错误。
这是服务器的工作方式,将长度接收到一个单独的变量中:
struct sockaddr_storage client_addr;
socklen_t client_addr_len = sizeof(client_addr); // This is an in+out parameter
n=recvfrom(..., (struct sockaddr *)&client_addr, &client_addr_len);
n=sendto(..., (struct sockaddr *)&client_addr, client_addr_len);
请注意,我使用了sockaddr_storage
而不是sockaddr_in
。 保证sockaddr_storage
足够大,可以容纳受支持的地址族的任何有效套接字地址类型,以便此代码与IPv6正向兼容。
同样,这是客户端的工作方式:
n=sendto(..., &server_addr, sizeof(server_addr));
do
{
struct sockaddr_storage peer_addr;
socklen_t peer_addr_len = sizeof(peer_addr);
n=recvfrom(..., (struct sockaddr *)&peer_addr, &peer_addr_len);
} while (!areSockAddrsEqual((struct sockaddr *)&server_addr, (struct sockaddr *)&peer_addr));
...
bool areSockAddrsEqual(struct sockaddr *addr1, struct sockaddr *addr2)
{
if (addr1->sa_family != addr2->sa_family)
return false;
switch (addr1->sa_family)
{
case AF_INET:
struct sockaddr_in *addr1_in = (struct sockaddr_in *)addr1;
struct sockaddr_in *addr2_in = (struct sockaddr_in *)addr2;
return (addr1_in->sin_port == addr2_in->sin_port &&
addr1_in->sin_addr.s_addr == addr2_in->sin_addr.s_addr);
...
// Other address families such as AF_INET6 left as an exercise
}
}
在这里,我们再次确保传递一个单独的socklen_t
指针以接收地址长度,然后我还添加了一个循环以确保接收到的实际数据包是我们希望从目标服务器获得的数据包。 如果我们改为接收到另一个数据包(例如,由于另一个对等方恰巧在错误的时间向我们发送了一个数据包),则我们将其忽略。
检查两个套接字地址是否相等有点麻烦,因为它取决于地址族,并且同时支持IPv4和IPv6是很棘手的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.