开发者

Sockets with pthreads issue

开发者 https://www.devze.com 2023-04-05 10:36 出处:网络
I\'m creating a server/client echo program. The client reads a string, sends to the server and the server sends the string back to the client.

I'm creating a server/client echo program. The client reads a string, sends to the server and the server sends the string back to the client.

Data structures:

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

typedef struct readStruct
{
    FILE *rsock;
    int sockfd;
 } readStruct;

Part of the main function:

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);
 }

And the functions:

Write function:

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);
}

Read function:

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);
}

It happens that writeProcess() works fine but readProcess() doesn't, apparently rsock gets an invalid memory address and I get Segmentation Fault.


Sorry, I have omitted some parts of the code, it would be very long.

Actually, I'm connecting the socket and the write function is working, but when it enters in the read function the file pointer loses its reference, at least I've seen this when debugging with GDB.

This problem has started occurring just after I have added the threads, when it was running on a single process it was working just fine


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

The above creates a disconnected TCP socket.

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

These open the same disconnected socket as two dysfunctional FILE*.

You need two different connected sockets to start with.

If the code you posted is a complete program, I can't see how it is supposed to work. Both reader and writer start with fgets() which should block them forever, since there would be no data.


Point 1 below is likely to be the real cause of your segmentation fault:

  1. fgets appends a null character to the end of the stored string. This means that you have to pass MAXDATASIZE-1 instead of MAXDATASIZE, otherwise an overflow may occur.

  2. Some might claim your program is leaking memory because you're assigning the return of fgets to rcvAux, which itself was pointing to another memory address that you manually allocated. After this assignment you won't be able to free it because the address of that allocated memory is lost.

  3. You are not checking the return values for socket() nor fdopen(). And you are not closing sockfd before exiting the application.

Update:

As pointed by R.. in comments, using fflush on non-writeable file-descriptor is undefined behavior.

Your code snippet doesn't show any connect() or bind()+listen()+accept() either. Your socket should first be connected in order to perform read and/or write operations. Checking the return values of each operation would have caught that.


I would start by checking if both fdopen() return good values, and bail if not.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号