Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 带pthreads的套接字问题_C_Sockets_Pthreads - Fatal编程技术网

C 带pthreads的套接字问题

C 带pthreads的套接字问题,c,sockets,pthreads,C,Sockets,Pthreads,我正在创建一个服务器/客户端echo程序。客户端读取字符串,发送到服务器,服务器将字符串发送回客户端 数据结构: typedef struct writeStruct { FILE *wsock; int sockfd; } writeStruct; typedef struct readStruct { FILE *rsock; int sockfd; } readStruct; 主要功能的一部分: main() { writeStruct *wr

我正在创建一个服务器/客户端echo程序。客户端读取字符串,发送到服务器,服务器将字符串发送回客户端

数据结构:

typedef struct writeStruct
{
    FILE *wsock;
    int sockfd;
} writeStruct;

typedef struct readStruct
{
    FILE *rsock;
    int sockfd;
 } readStruct;
主要功能的一部分:

main()
{
    writeStruct *writeData;
    readStruct *readData;
    writeData = malloc(sizeof(writeData));
    readData = malloc(sizeof(readData));

    pthread_t write;
    pthread_t read;

    FILE *rsock, *wsock;

    int sockfd;
    sockfd = socket(AF_INET, SOCK_STREAM, 0);

    rsock = fdopen(sockfd, "r");
    wsock = fdopen(sockfd, "w");

    writeData->wsock = wsock;
    readData->rsock = rsock;

    writeData->sockfd = sockfd;
    readData->sockfd = sockfd;

    pthread_create(&write, NULL, writeProcess, (void*)writeData);
    pthread_create(&read, NULL, readProcess, (void*)readData);

    pthread_join(write, NULL);
    pthread_join(read, NULL);
 }
void *writeProcess(void *writeData)
{
    FILE *wsock = ((writeStruct*)writeData)->wsock;
    int sockfd = ((writeStruct*)writeData)->sockfd;
    int success = 0;
    char *buf = malloc(sizeof(char) * MAXDATASIZE);

    while(fgets(buf, MAXDATASIZE, stdin) != NULL)
    {
        fputs(buf, wsock);
        fflush(wsock);
    }
    fputs(buf, wsock);
    free(buf);
    shutdown(sockfd, SHUT_WR);
}
void *readProcess(void *readData)
{
    FILE *rsock = ((readStruct*)readData)->rsock;
    int sockfd = ((readStruct*)readData)->sockfd;
    char *rcv, *rcvAux;
    rcv = malloc(sizeof(char) * MAXDATASIZE);
    rcvAux = malloc(sizeof(char) * MAXDATASIZE);

    rcvAux = fgets(rcv, MAXDATASIZE, rsock);
    while(rcvAux != NULL)
    {
        fflush(rsock);
        numCharsRcv += strlen(rcv);
        numLinesRcv++;
        printf("%s", rcv);
        rcvAux = fgets(rcv, MAXDATASIZE, rsock);
    }
    printf("%s", rcv);
    free(rcv);
}
以及功能:

写入功能:

main()
{
    writeStruct *writeData;
    readStruct *readData;
    writeData = malloc(sizeof(writeData));
    readData = malloc(sizeof(readData));

    pthread_t write;
    pthread_t read;

    FILE *rsock, *wsock;

    int sockfd;
    sockfd = socket(AF_INET, SOCK_STREAM, 0);

    rsock = fdopen(sockfd, "r");
    wsock = fdopen(sockfd, "w");

    writeData->wsock = wsock;
    readData->rsock = rsock;

    writeData->sockfd = sockfd;
    readData->sockfd = sockfd;

    pthread_create(&write, NULL, writeProcess, (void*)writeData);
    pthread_create(&read, NULL, readProcess, (void*)readData);

    pthread_join(write, NULL);
    pthread_join(read, NULL);
 }
void *writeProcess(void *writeData)
{
    FILE *wsock = ((writeStruct*)writeData)->wsock;
    int sockfd = ((writeStruct*)writeData)->sockfd;
    int success = 0;
    char *buf = malloc(sizeof(char) * MAXDATASIZE);

    while(fgets(buf, MAXDATASIZE, stdin) != NULL)
    {
        fputs(buf, wsock);
        fflush(wsock);
    }
    fputs(buf, wsock);
    free(buf);
    shutdown(sockfd, SHUT_WR);
}
void *readProcess(void *readData)
{
    FILE *rsock = ((readStruct*)readData)->rsock;
    int sockfd = ((readStruct*)readData)->sockfd;
    char *rcv, *rcvAux;
    rcv = malloc(sizeof(char) * MAXDATASIZE);
    rcvAux = malloc(sizeof(char) * MAXDATASIZE);

    rcvAux = fgets(rcv, MAXDATASIZE, rsock);
    while(rcvAux != NULL)
    {
        fflush(rsock);
        numCharsRcv += strlen(rcv);
        numLinesRcv++;
        printf("%s", rcv);
        rcvAux = fgets(rcv, MAXDATASIZE, rsock);
    }
    printf("%s", rcv);
    free(rcv);
}
读取功能:

main()
{
    writeStruct *writeData;
    readStruct *readData;
    writeData = malloc(sizeof(writeData));
    readData = malloc(sizeof(readData));

    pthread_t write;
    pthread_t read;

    FILE *rsock, *wsock;

    int sockfd;
    sockfd = socket(AF_INET, SOCK_STREAM, 0);

    rsock = fdopen(sockfd, "r");
    wsock = fdopen(sockfd, "w");

    writeData->wsock = wsock;
    readData->rsock = rsock;

    writeData->sockfd = sockfd;
    readData->sockfd = sockfd;

    pthread_create(&write, NULL, writeProcess, (void*)writeData);
    pthread_create(&read, NULL, readProcess, (void*)readData);

    pthread_join(write, NULL);
    pthread_join(read, NULL);
 }
void *writeProcess(void *writeData)
{
    FILE *wsock = ((writeStruct*)writeData)->wsock;
    int sockfd = ((writeStruct*)writeData)->sockfd;
    int success = 0;
    char *buf = malloc(sizeof(char) * MAXDATASIZE);

    while(fgets(buf, MAXDATASIZE, stdin) != NULL)
    {
        fputs(buf, wsock);
        fflush(wsock);
    }
    fputs(buf, wsock);
    free(buf);
    shutdown(sockfd, SHUT_WR);
}
void *readProcess(void *readData)
{
    FILE *rsock = ((readStruct*)readData)->rsock;
    int sockfd = ((readStruct*)readData)->sockfd;
    char *rcv, *rcvAux;
    rcv = malloc(sizeof(char) * MAXDATASIZE);
    rcvAux = malloc(sizeof(char) * MAXDATASIZE);

    rcvAux = fgets(rcv, MAXDATASIZE, rsock);
    while(rcvAux != NULL)
    {
        fflush(rsock);
        numCharsRcv += strlen(rcv);
        numLinesRcv++;
        printf("%s", rcv);
        rcvAux = fgets(rcv, MAXDATASIZE, rsock);
    }
    printf("%s", rcv);
    free(rcv);
}
writeProcess()工作正常,但readProcess()工作不正常,显然rsock得到了一个无效的内存地址,我得到了分段错误


对不起,我遗漏了部分代码,可能会很长

实际上,我正在连接套接字,写函数正在工作,但是当它进入读函数时,文件指针失去了它的引用,至少我在用GDB调试时看到了这一点


在我添加线程之后,这个问题就开始出现了,当它在单个进程上运行时,它运行得很好

我会首先检查fdopen()是否都返回了正确的值,如果没有返回,则检查bail。

我会首先检查fdopen()是否都返回了正确的值,如果没有,请保释。

下面的第1点很可能是造成细分错误的真正原因:

  • fgets
    在存储字符串的末尾追加一个空字符。这意味着您必须传递
    MAXDATASIZE-1
    ,而不是
    MAXDATASIZE
    ,否则可能会发生溢出

  • 有些人可能会声称您的程序正在泄漏内存,因为您正在将
    fgets
    的返回值分配给
    rcvAux
    ,它本身指向您手动分配的另一个内存地址。在此分配之后,您将无法
    释放它,因为该分配内存的地址丢失

  • 您没有检查
    socket()
    fdopen()
    的返回值。在退出应用程序之前,您不会关闭
    sockfd

  • 更新

    正如注释中所指出的,对不可写文件描述符使用
    fflush
    是未定义的行为


    您的代码段也不显示任何
    connect()
    bind()
    +
    listen()
    +
    accept()
    。为了执行读和/或写操作,应首先连接套接字。检查每个操作的返回值会发现这一点。

    下面的第1点可能是分段错误的真正原因:

    int sockfd;
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    
  • fgets
    在存储字符串的末尾追加一个空字符。这意味着您必须传递
    MAXDATASIZE-1
    ,而不是
    MAXDATASIZE
    ,否则可能会发生溢出

  • 有些人可能会声称您的程序正在泄漏内存,因为您正在将
    fgets
    的返回值分配给
    rcvAux
    ,它本身指向您手动分配的另一个内存地址。在此分配之后,您将无法
    释放它,因为该分配内存的地址丢失

  • 您没有检查
    socket()
    fdopen()
    的返回值。在退出应用程序之前,您不会关闭
    sockfd

  • 更新

    正如注释中所指出的,对不可写文件描述符使用
    fflush
    是未定义的行为

    您的代码段也不显示任何
    connect()
    bind()
    +
    listen()
    +
    accept()
    。为了执行读和/或写操作,应首先连接套接字。检查每个操作的返回值会发现这一点

    int sockfd;
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    
    上述操作将创建一个断开连接的TCP套接字

    rsock = fdopen(sockfd, "r");
    wsock = fdopen(sockfd, "w");
    
    它们打开与两个功能异常的
    文件*
    相同的断开的插座

    首先需要两个不同的连接插座

    如果你发布的代码是一个完整的程序,我看不出它应该如何工作。读卡器和写卡器都以
    fgets()
    开始,这将永远阻止它们,因为没有数据

    上述操作将创建一个断开连接的TCP套接字

    rsock = fdopen(sockfd, "r");
    wsock = fdopen(sockfd, "w");
    
    它们打开与两个功能异常的
    文件*
    相同的断开的插座

    首先需要两个不同的连接插座


    如果你发布的代码是一个完整的程序,我看不出它应该如何工作。读写器都从
    fgets()
    开始,这将永远阻止它们,因为没有数据。

    首先,对打开读取的文件调用
    fflush
    是未定义的行为。。。即使它没有可怕的崩溃,它也不会做你想做的事。谁教你这样使用
    fflush
    的?@R..:说得好!但是,我认为它设置了
    errno
    (EBADF?)。不确定它是否真的没有定义。无论如何,我认为这给出了一个真正的答案。7.19.5.2:“如果流指向一个输出流或一个更新流,其中没有输入最新的操作,则fflush函数会导致将该流的任何未写入数据发送到主机环境中写入文件;否则,行为是未定义的。”@R..:oh,我错了:)谢谢你查找!!首先,对打开读取的文件调用
    fflush
    是未定义的行为。。。即使它没有可怕的崩溃,它也不会做你想做的事。谁教你这样使用
    fflush
    的?@R..:说得好!但是,我认为它设置了
    errno
    (EBADF?)。不确定它是否真的没有定义。无论如何,我认为这给出了一个真正的答案。7.19.5.2:“如果流指向一个输出流或一个更新流,其中没有输入最新的操作,则fflush函数会导致将该流的任何未写入数据发送到主机环境中写入文件;否则,行为是未定义的。”@R..:oh,我错了:)谢谢你查找!!即使在可写文件描述符上,
    fflush
    如果处于“读取模式”(如果最后一个操作是读取),也是UB。和switc