【问题标题】:Socket Programming C/C++ - recv function hangs?套接字编程 C/C++ - recv 函数挂起?
【发布时间】:2009-12-11 12:11:09
【问题描述】:

我的 recv 函数在从服务器获取响应时挂起。

c/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 Progress。 请查看代码并提出问题所在。??

【问题讨论】:

  • 您应该使用 sizeof(server_addr.sin_zero) 而不是幻数 8。或者最好还是将整个结构归零,然后设置您感兴趣的字段。
  • 嗨,尼尔,您能否详细说明一下,因为我尝试了 sizeof(server_addr.sin_zero) 而不是数字 8,但仍然没有运气。Thnx。

标签: c sockets


【解决方案1】:

您的代码将在 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。您没有在代码 sn-p 中声明或初始化“a”。

【讨论】:

    【解决方案2】:

    您的代码将在 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。您没有在代码 sn-p 中声明或初始化 'a'。" by notacat

    我正在编写我在 win 上使用 c++ 实现的早期 winsock 1.0 和 1.1 的副本。 我的代码一直工作到 recv() 调用,然后就挂在那里......我知道阻塞\非阻塞套接字,但这不是我需要的解决方案。由于我在 Wireshark 或类似工具中看到了我的请求,我知道服务器正在端口 80 上接收我的字符串结束请求,并且由于我的客户端和服务器在 'net.这使我相信我没有提交正确的请求。好吧,作者(notaket)就在现场!一旦我更改为他的请求(“GET /index.html HTTP/1.1\r\nHost: www.example.com\r\n\r\n”),一切似乎都像魅力一样!谢谢!!

    【讨论】:

      【解决方案3】:

      recv 应该挂起,直到您从服务器获得响应,您是否声明正在发送响应。
      尝试使用 wireshark 或类似的东西来嗅探网络,看看实际响应是否到来。

      【讨论】:

      • 实际上在 recv() 挂起后,我尝试了 ctrl+alt+del。通过执行此任务管理器打开但我关闭了此任务管理器(未杀死任何进程),突然它给了我一次响应。但是我的程序仍处于冻结状态。
      【解决方案4】:

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

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

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

      【讨论】:

        【解决方案5】:

        尝试使用非阻塞模式。即如果没有要读取的数据,recv 将返回,因此请处理这种情况(在 while 循环中或使用 select。这取决于您)

        有关 recv 的更多信息,假设您使用的是 POSIX 兼容系统)阅读此 http://www.opengroup.org/onlinepubs/009695399/functions/recv.html

        【讨论】:

          【解决方案6】:

          Ummm....你为什么要关闭套接字....

          bytes_send = 发送(袜子,一个,strlen(a),0); bytes_send = 关机(袜子,1); /*** 我认为是问题所在! ***/ bytes_recieved = recv(sock, recv_data, 4096, 0);

          但你继续在代码中从被关闭的同一个套接字接收??

          希望这会提示您正确的方向。

          【讨论】:

          • 谢谢。汤姆回答。但是关机(袜子,1);没有关闭套接字。它只是说明不允许发送(不再发送。)。即使我删除了这一行,我的 recv() 也会挂起。
          • @Vishal: 好的...developerweb.net/forum/showthread.php?t=2940 - 关于何时使用关机有一个有趣的讨论。代码处于同步模式,可能之前已经发生了数据接收关闭并因此挂起。你有没有想过……?对不起,如果我在这里帮不上什么忙... :(
          猜你喜欢
          • 2013-06-09
          • 1970-01-01
          • 2019-10-14
          • 1970-01-01
          • 2014-07-13
          • 2013-11-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多