无法连接得到错误的文件描述符错误后,接收数据(Unable to receive data afte

2019-10-23 08:21发布

我正在使用C中的P线程多线程服务器应用程序(Linux)的。 我的系统是双boot.Windows 7和Ubuntu的。 我重新启动我的电脑并启动到Windows,从Ubuntu的,重新启动我的服务器应用程序正在Fine.After我再次从Windows启动到Ubuntu之前。 并开始了我的服务器,我开始变得当客户端连接下面的错误。

recv failed: Bad file descriptor

下面是我的代码:

MAIN.C

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h> //for socket,AF_INET,SOCK_STREAM
#include <arpa/inet.h> //for sockaddr_in
#include <string.h>   //for memset()  
#include <pthread.h>
#include <fcntl.h>
#include <unistd.h>
#include "extern.h" 

#define MAX_CONNECTIONS  5

int main(int argc, char** argv) {

    int sock_desc = 0, connfd = 0,listenfd =0;
    struct sockaddr_in serv_addr;
    int clntSock; 
    struct sockaddr_in echoClntAddr; 
    unsigned int clntLen; 
    char sendBuff[1025];
    char recvBuff[10025];
    int n = 0;
    pthread_t thr;



    sock_desc = socket(AF_INET, SOCK_STREAM, 0); 

    if(sock_desc < 0 )
       dieWithError("Unable to open Socket\n");  

    memset(&serv_addr,0,sizeof(serv_addr)); 

    serv_addr.sin_family = AF_INET ;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_addr.sin_port = htons(7024);

    if(bind(sock_desc, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) 
       dieWithError("bind failed\n");

    if(listen(sock_desc,MAX_CONNECTIONS) < 0)
       dieWithError("listen failed\n");  

     file = fopen("testServer.txt", "w");

      clntSock = sizeof(struct sockaddr);
      int i =0;
      fcntl(sock_desc, F_SETFL, fcntl(sock_desc, F_GETFL, 0) | O_NONBLOCK);

      while(1)
    {

        connfd = accept(sock_desc, (struct sockaddr *)&echoClntAddr,(socklen_t*)&clntSock);

      if(connfd > 0){  
         puts("Connection accepted");

        if( pthread_create( &thr, NULL ,  connection_handler , (void*) &connfd) < 0)
        {
            perror("could not create thread");
            return 1;
        }

        puts("Handler assigned");
        }    
    }

    if (connfd < 0)
    {
        perror("accept failed");
        return 1;
    }


       return (EXIT_SUCCESS);
}

void dieWithError(char *errormsg){
     printf("%s", errormsg);  
}

HandleConnection.c

#include <stdio.h> 
#include <sys/socket.h> 
#include <unistd.h> 
#include <string.h>
#include "extern.h"



void *connection_handler(void *socket_desc)
{

    int sock = *(int*)socket_desc;
    t_data.t_id = sock;

    int read_size;
    char *message , client_message[2000];

    while( (read_size = recv(sock , client_message , 2000 , 0)) > 0 )
    {

       client_message[read_size] = '\0';
           t_data.msg = client_message; 


           printf("%s",client_message); 

        memset(client_message, 0, 2000);
    }

    if(read_size == 0)
    {
        puts("Client disconnected");
        fflush(stdout);
    }
    else if(read_size == -1)
    {
        perror("recv failed");
    }

    return 0;
} 

我试图通过重新启动我的电脑,但同样的问题persists.Please帮助。

Answer 1:

(你观察到的问题无关,与双启动机器上运行。)

如所示的代码通过使用相同的变量的地址为每个传入的连接传递的套接字描述符给线程函数引入了比赛。

如果比赛occures accept()将返回更快的第二次。 禁食线程处理器来存储它得以通过所指向的地址通过执行:

int sock = *(int*)socket_desc;

在你设置为无阻塞这个最likley情况下,当只有一个连接进来,处理程序得到的地址监听套接字specfic情况connfd在和并行通过accept()被再次呼吁(非阻塞)监听套接字,并没有传入的连接正在等待和accept()立即返回,并设置connfd为-1。 出现这种情况快于前一个连接处理程序可以调用

int sock = *(int*)socket_desc;

与这家店的-1

要观察这个效果( 不解决这个问题 )修改代码如下:

int result = accept(sock_desc, (struct sockaddr *)&echoClntAddr, &clntSock);
if (0 > result)
{
  perror("accept() failed");
}
else
{
  connfd = result;

  puts("Connection accepted");

  if( pthread_create( &thr, NULL ,  connection_handler , (void*) &connfd) < 0)
  {
    ...

然后,处理程序将开始是这样的:

    void *connection_handler(void * pv)
    {
      int sock = *((int*) pv);
      fprintf("sock = %d\n", sock);
      ...

为了解决您的问题有两种方法:

  1. 滥用线程函数void*参数传递的int

     socklen_t clntSock = ...; ... connfd = accept(sock_desc, (struct sockaddr *)&echoClntAddr, &clntSock); if (0 <= connfd) { if (pthread_create( &thr, NULL, connection_handler, (void *) connfd) < 0) { ... 

    然后,处理程序将开始是这样的:

     void *connection_handler(void * pv) { int sock = (int) pv; ... 

    这是一个常见的,但有些“哈克”的解决方案,其依赖于一个指针是至少一样宽的int

  2. 使用的一个单独的实例int存储的结果accept()

     socklen_t clntSock = ...; ... connfd = accept(sock_desc, (struct sockaddr *)&echoClntAddr, &clntSock); if (0 <= connfd) { int * pconnfd = malloc(sizeof *pconnfd); if (NULL == pconnfd) ... // fail and leave here *pconnfd = connfd; if (pthread_create(&thr, NULL, connection_handler, pconnfd) < 0) { ... 

    然后,处理程序将开始是这样的:

     void *connection_handler(void * pv) { int connfd = *((int *) pv); free(pv); ... 

    这是一个干净和便携式方法,将具有一对附加的呼叫到成本malloc() / free()

在代码其他校正如上所示:

  • 限定伟驰地址被传递到可变accept()socklen_t作为第三参数来accept()被定义为socklen_t * 。 如果指针传递到其他的东西,这“东西”是不同的大小比socklen_t accept()会遇到不确定的行为。

  • 测试的结果accept()<0为误差作为0为文件/套接字描述符有效的值。



文章来源: Unable to receive data after connection getting Bad file Descriptor error