非循环while循环,同时使用recv

时间:2016-01-12 18:40:49

标签: c sockets while-loop

我正在尝试从客户端程序接收一条大消息,两者都使用SOCK_STREAM套接字,因此,我必须在我的recv调用上使用while循环。然而,它冻结了,似乎没有在循环中打印任何东西。

这是服务器的代码

enter code here

Class A
 {
   String val;
    protected A( )
     {
     }
    protected A(String val)
     {
       this.val=val;
     }
   protected void setVal( String val)
    {
       this.val=val;
    } 
   public String getVal()
    {
      return val;
    }    
}
class B extends A
  {
     B()
     {
       super();
     }     
    public val setVal(String val)
    {
      super.val=val;    
    }
} 
class C extends A
{
    C(String val)
    {
      super(val);
    }
}

这是客户端的代码

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <unistd.h> 
#include <stdlib.h>
#include <arpa/inet.h>

#define BUFSIZE 1024
extern int errno;
void error(char *msg)
{
    perror(msg);
    exit(0);
}

int main(int argc, char *argv[])
{
     int sock, newsock, len, fromlen, n;
     unsigned short port;
     struct sockaddr_in server, from;
     char buffer[BUFSIZE];
     char *msg = "I Got your message";

     if (argc < 2) {
         fprintf(stderr,"usage %s portnumber\n",argv[0]);
         exit(0);
     }
     port = (unsigned short) atoi(argv[1]);
     sock=socket(AF_INET, SOCK_STREAM, 0);
     if (sock < 0) error("Opening socket");
     server.sin_family=AF_INET;
     server.sin_addr.s_addr=INADDR_ANY;
     server.sin_port=htons(port);  
     len=sizeof(server);
     if (bind(sock, (struct sockaddr *)&server, len) < 0) 
          error("binding socket");
     fromlen=sizeof(from);
     if (listen(sock,5) < 0) 
          error("listening");

     // accept connections loop
     while (1) {
         newsock=accept(sock, (struct sockaddr *)&from, &fromlen);
         if (newsock < 0) error("Accepting");
         printf("A connection has been accepted from %s\n",
                 inet_ntoa((struct in_addr)from.sin_addr));

         // receive long messages loop
         while ((n = recv(newsock,buffer,BUFSIZE-1,0)) > 0){
            buffer[n] = '\0';
            printf("\n message: \n%s\n", buffer);
         }

        len = strlen(msg);
        n = send(newsock,msg,len,0);
        if (n < len) error("Error writing");

       if (close(newsock) < 0) error("closing");           
     }
     return 0; // we never get here 
}

最终目标是在服务器端接收完整的消息,然后向客户端发送确认消息已收到。

1 个答案:

答案 0 :(得分:2)

这个条件:

 (n = recv(newsock,buffer,BUFSIZE-1,0)) > 0
除非远程关闭套接字或系统调用返回错误,否则

将始终为true。否则,如果没有从客户端发送数据,它将阻止。

在STREAM套接字上,您必须预期字节流而不做出假设,如何在多次调用recv()时将其分块。一种常见的解决方案是首先发送(和接收)长度信息,然后调用recv直到总共收到 length 字节。

您的特殊情况的另一个选项(“快速修复”)可能是在发送大消息后关闭客户端中套接字的发送方向:

shutdown(fd, SHUT_WR);

之后,recv系统调用确实将返回0并且服务器可以发送其确认。但是,在调用shutdown()后,客户端将无法发送数据。