2012-05-06 73 views
2

这是关于UDP套接字的一个非常基本的问题。我自己编写了一些使用它们的服务器/客户端应用程序,但我现在卡住了,无法看到问题出在哪里。C中的双向UDP套接字

我想要做一个服务器和客户端,它可以发送和接收数据报。因此,服务器等待来自客户端的确定套接字的请求,当它通过它接收到某个请求时,它将其答案发送给客户端。它只要服务器获得请求并发回答案,但客户端永远不会得到它。

我在这里展示一些剥离代码,只需连接的基本组成部分:

SERVER:

if ((socket_id = socket(PF_INET, SOCK_DGRAM, 0)) == -1) { 
    return; 
} 

bzero(&server_socket, sizeof(server_socket)); 
server_socket.sin_family = AF_INET; 
server_socket.sin_addr.s_addr = INADDR_ANY; 
server_socket.sin_port = htons(8724); 

if (bind(socket_id, (struct sockaddr *) &server_socket, sizeof(server_socket)) == -1) { 
    return; 
} 

bzero(dgram_buffer, 1024); 
client_socket_sz = sizeof(client_socket); 
if((dgram_length = recvfrom(socket_id, dgram_buffer, 1024, 0, (struct sockaddr *) &client_socket, (socklen_t *) &client_socket_sz)) == -1) { 

    return; 
} 
if (sendto(socket_id, msg_buffer, offset, 0, (struct sockaddr *) &client_socket, (socklen_t) client_socket_sz) < 0) { 

    return; 
} 
printf("%s\n", msg_buffer); 

客户:

if ((socket_id = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { 
     return; 
} 

if ((hostp = gethostbyname(hostname)) == 0) { 
    return; 
} 
bzero((char *) &client_socket, sizeof(client_socket)); 
client_socket.sin_family = AF_INET; 
client_socket.sin_port = htons(8724); 
bcopy(hostp->h_addr, (char *) &client_socket.sin_addr, hostp->h_length); 

bzero(msg_buffer,sizeof(msg_buffer)); 
memcpy(msg_buffer,"mensaje\0",sizeof("message")); 

socklen_t client_socket_len = sizeof(struct sockaddr_in); 
if (sendto(socket_id, msg_buffer, sizeof(msg_buffer), 0, (struct sockaddr *) &client_socket, client_socket_len) < 0) { 
    return; 
} 
bzero(msg_buffer,sizeof(msg_buffer)); 
if(recvfrom(socket_id, msg_buffer, sizeof(msg_buffer), 0, (struct sockaddr *) &client_socket, &client_socket_len) == -1) { 
    return; 
} 
printf("%s\n", msg_buffer); 

(我知道缓冲区及其内容没有得到很好的对待;我在我的真实应用程序上正确地做到了这一点,我只是输入它以获得快速测试)

任何人都可以给它一看,并告诉我,如果一些设置是错误的?我在网上看到了数百个例子,回顾了我的旧代码...无济于事。也许我已经在这上了很多个小时,而我只是略过了这个明显的。

在此先感谢。

+0

你能给我们一些东西编译吗? –

+0

顺便说一句,它是否与主机名称==“本地主机” - 即。客户端和服务器在同一台机器上?我只是编译它,它在OS X上工作 –

+0

我尝试切换机器我执行服务器(远程)和客户端(本地),然后它是服务器(现在本地),没有得到任何消息。所以我在两个不同的远程机器上执行了两个(尽管在同一个网络上),至少我在这里发布的这个简单代码执行得很好。这是否意味着这是我的本地机器的问题? – freieschaf

回答

0

您需要绑定两个套接字。

您已将服务器绑定到知名端口。
您还应该将客户端绑定到端口0.这意味着操作系统为该会话选择任意端口。当套接字被绑定时,你会得到数据包到那个端口。

+0

感谢您的快速回复:)我已经尝试过,但客户端无论如何都得不到回应。 – freieschaf

+0

尝试窥探流量(tcpdump/wireshark)并查看发送的内容。使用'netstat'来查看哪个进程监听哪个端口。 – ugoren

+0

我在服务器和客户端都使用strace,它只是表明:服务器已收到请求并发送响应,客户端发送请求并一直等待响应。当它挂在那里时,我没有发现服务器在客户端执行netstat的端口。那应该是什么意思? – freieschaf

0

只是一个猜测。尝试在'while'循环中从套接字读取数据。 类似的东西:

int received = 0; 
int tmp; 
int expected = ... 
while(received != expected){ 
    tmp = recvfrom(socket_id, msg_buffer, sizeof(msg_buffer), 0, (struct sockaddr *) &client_socket, &client_socket_len) 
    if(tmp == -1){ ... } 
    received += tmp; 
} 
+0

事情是,我不知道我期待的消息的大小。实际上,我的应用程序中的工作流程基于可变大小,所以我无法循环recvfrom()。 – freieschaf

+0

特别是在消息大小不同的情况下,您必须使用read()或recv()的返回值。 – wildplasser

+0

@freieschaf:如果你不知道传入数据的大小,你可能不得不忍受丢弃你的数据包的一部分,或者你将不得不分配足够大的缓冲区来容纳最大的数据包可能的UDP数据包(64k,IIRC)。欢迎来到输入验证的世界。 – tbert