2009-12-11 151 views
8

我的recv函数在从服务器获取响应时挂起。在CSocket编程C/C++ - recv函数挂起?

客户端代码/ C++:

void sockStuff() { 

int sock, bytes_recieved,bytes_send; 
char send_data[1024], recv_data[4096]; 

struct hostent *host; 
struct sockaddr_in server_addr; 

host = gethostbyname("127.0.0.1"); 

if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { 
    perror("SocketError"); 
    exit(1); 
} 
server_addr.sin_family = AF_INET; 
server_addr.sin_port = htons(50500); 
server_addr.sin_addr = *((struct in_addr *) host->h_addr); 
bzero(&(server_addr.sin_zero), 8); 


if (connect(sock, (struct sockaddr *) &server_addr, sizeof(struct sockaddr)) 
    == -1) { 
    perror("ConnectToError"); 
    exit(1); 
} 


    bytes_send = send(sock, a, strlen(a), 0); 
    bytes_send = shutdown(sock, 1); 


bytes_recieved = recv(sock, recv_data, 4096, 0); //Where the program hangs?? 
recv_data[bytes_recieved] = '\0'; 
printf("\nRecieved data = %s ", recv_data); 
cout << endl << endl; 

shutdown(sock,2); 



} 

我的客户是C/C++和服务器端是OpenEdge进展。 请看代码,并提出这个错误。

+0

您应该使用sizeof(server_addr.sin_zero)而不是magic number 8.或者更好的是将整个结构归零,然后设置您感兴趣的字段。 – 2009-12-11 22:16:21

+0

您好Neil,请您详细说明这一点,因为我试过sizeof( server_addr.sin_zero)而不是8号,但仍然没有运气.Thnx。 – Vishal 2009-12-14 08:24:40

回答

1

recv应该挂起,直到你得到服务器的响应,你说你的响应正在发送。
尝试wireshark或类似的东西来嗅探网络,看看实际的响应是否即将到来。

+0

事实上,在recv()挂起后,我尝试了ctrl + alt + del.By这个任务管理器打开了,但是我关闭了这个任务管理器(并没有终止任何进程),突然它给了我一次响应。但是我的程序仍处于冻结状态。 – Vishal 2009-12-11 12:24:59

1

嗯....你为什么要关闭插座....

 
bytes_send = send(sock, a, strlen(a), 0); 
    bytes_send = shutdown(sock, 1); /*** That I think is the problem! ***/ 


bytes_recieved = recv(sock, recv_data, 4096, 0); 

可是你的代码继续从同一个插座,这是关机接受?

希望这个提示你在正确的方向, 最好的问候, 汤姆。

+0

Thnx。汤姆回复。 但是关机(袜子,1);不是关闭套接字,它只是告诉发送是不允许的(没有更多发送)。即使我删除了这一行,我的recv()挂起。 – Vishal 2009-12-11 12:50:14

+0

@Vishal:好的... http://www.developerweb.net/forum/showthread.php?t = 2940 - 有一个有趣的讨论abotu什么时候使用shutdown ..代码是在同步模式下,它可能是可能的数据的接收已经发生在关机之前并因此挂起。你有没有想过...?对不起,如果我在这里没有太多的帮助...... :( – t0mm13b 2009-12-11 13:20:16

1

只要套接字处于阻塞模式,Recv就会阻塞直到套接字有信息读取,您可以使用fcntl来更改它。

如果你想知道它为什么挂起来,我猜测当你关闭套接字上的写入管道时(同样,你可能想使用常量SHUT_WR,因为它是更好的样式),服务器接收EOF并假定您正在断开连接,但如果服务器设置为处理它,情况可能不会如此。

我建议考虑将套接字设置为非阻塞模式,然后调用select,这将阻塞,直到套接字可读/可写/或超时被触发。取决于你在做什么,这会有所作为。

8

您的代码将阻止recv调用,直到服务器发回任何数据。既然这没有发生,也许你应该问自己,如果你的客户发送完整的请求。在收到完整的请求之前,服务器可能不会开始发送响应。

如果您的客户端/服务器协议基于文本,如HTTP或SMTP,您确定您的响应正确终止?服务器可以期待CR + LF( '\ r \ n'),而不是仅仅LF( '\ n')或它期望一个空行终止请求:

char *request = "GET /index.html HTTP/1.1\r\nHost: www.example.com\r\n\r\n"; 

PS。您不要在代码片段中声明或初始化'a'。

4

您的代码将在recv调用中阻塞,直到服务器发回任何数据为止。既然这没有发生,也许你应该问自己,如果你的客户发送完整的请求。在收到完整的请求之前,服务器可能不会开始发送响应。

如果您的客户端/服务器协议基于文本,如HTTP或SMTP,您确定您的响应正确终止?服务器可能期望CR + LF('\ r \ n')而不是仅LF('\ n'),或者它期望一个空行来终止请求:

char * request =“GET/index。 html HTTP/1.1 \ r \ n主机:www.example.com \ r \ n \ r \ n“; PS。你不声明或初始化你的代码片段中的'a'。“by notacat

我正在研究早期的winsock 1.0和1.1版本的实现,在C++上的win。 我的代码一直工作到recv )呼叫,然后只是挂在那里......我知道有关阻塞\非阻塞套接字,但那不是我需要的解决方案。因为我看到我的请求在wireshark或类似的我知道该服务器正在接收我的字符串请求的结束因为我的客户端和服务器之间没有通信,导致我相信我没有提交正确的请求,好吧,作者(notaket)就在现场! 。只要我改变他的请求(“GET /index.html HTTP/1.1 \ r \ n主机:www.example.com \ r \ n \ r \ n”),似乎所有的工作都像一个魅力! !!