调用recv()阻止输入

时间:2014-08-04 13:21:48

标签: c sockets recv

我遇到套接字问题。我有一台服务器和一个客户端。

该计划的目的:

客户端/服务器连接(两者都互相发送消息) 客户端发送消息; 服务器读取消息; 服务器将消息发送回客户端。

但我有一个死锁,因为客户端和服务器都在等待接收消息。代码:

Server.c

message = "Client connection handler ok\n";
write(sock , message , strlen(message));

message = "type something and i'll repeat what you type \n";
write(sock , message , strlen(message));

//Receive a message from client
while( (read_size = recv(sock , client_message , 2000 , 0)) > 0 )
{
    puts(client_message);

    //Send the message back to client
    write(sock , client_message , strlen(client_message));

    bzero(client_message,2000);
}

Client.c

//Here I print the two messages You can see server side code:
//- Client connection handler ok
//- type something and i'll repeat what you type
while( (read_size = recv(sockfd , client_message , 2000 , 0)) > 0 )
{
     printf("%s\n",client_message);
     bzero(client_message,2000);
}

在代码的执行中,我在while内部的客户端和服务器中都被阻止了。

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

您正在寻找select功能。你告诉select等待 stdin和你的插座。

您的客户端将如下所示(未经测试的代码):

/* This is a bit mask where each bit corresponds to a file descriptor.
   It is an in/out parameter, so you set some bits to tell select what
   to wait on, and then select sets bits in it to tell you what fd has
   data waiting for you to read. */
fd_set read_fds;

while(1){
    int fd_max = STDIN_FILENO;

    /* Set the bits for the file descriptors you want to wait on. */
    FD_ZERO(&read_fds);
    FD_SET(STDIN_FILENO, &read_fds);
    FD_SET(sockfd, &read_fds);

    /* The select call needs to know the highest bit you set. */    
    if( sockfd > fd_max ) { fd_max = sockfd; }

    /* Wait for any of the file descriptors to have data. */
    if (select(fd_max + 1, &read_fds, NULL, NULL, NULL) == -1)
    {
      perror("select:");
      exit(1);
    }

    /* After select, if an fd's bit is set, then there is data to read. */      
    if( FD_ISSET(sockfd, &read_fds) )
    {
        /* There is data waiting on your socket.  Read it with recv(). */
    }

    if( FD_ISSET(STDIN_FILENO, &read_fds )
    {
        /* The user typed something.  Read it fgets or something.
           Then send the data to the server. */
    }
}

从stdin读取数据后,请不要忘记将数据发送到服务器。在您发布的代码中,您实际上并未向服务器发送任何数据,因此服务器无法唤醒。

答案 1 :(得分:0)

最低协议将通过以下方式实现:

//Here I print the two messages You can see server side code:
//- Client connection handler ok
//- type something and i'll repeat what you type
while( (read_size = recv(sockfd , client_message , 2000 , 0)) > 0 )
{
  printf("%s\n",client_message);
  bzero(client_message,2000);

  if (0 == strcmp(client_message, "type something and i'll repeat what you type \n")
  {
    char buffer[256] = {0};
    fgets(buffer, sizeof(buffer), stdin);
    write(sockfd, buffer, strlen(buffer)+1);
  }
}

为了可读性,省略了上述示例中的任何错误检查。

如果(幸运的话)请求客户端键入任何内容的字节流部分(作为一个片段),调用fgets()来读取标准输入的行,然后尝试发送通过套接字输出。


另请注意,读取/写入套接字不一定会读取/写入大量字节,因为呼叫被告知读/写。因此,为了确保读取/写入所请求的数据量,代码需要循环这些调用,检查其结果,直到最终传输所请求的数据量。有关此内容的更多信息,包括在此处显示如何执行此操作的答案的链接:https://stackoverflow.com/a/24536689/694576