2011-09-14 111 views
0

我正在創建服務器/客戶端回顯程序。客戶端讀取一個字符串,發送到服務器,服務器將字符串發送回客戶端。pthreads問題的套接字

數據結構:

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

它發生writeProcess()工作正常,但readProcess()不,顯然rsock得到無效的內存地址,我得到段錯誤。


對不起,我已經省略了代碼的一些部分,它會很長。

實際上,我連接套接字並且寫入函數正在工作,但是當它進入讀取函數時,文件指針會丟失其引用,至少我在使用GDB進行調試時看到了這一點。

這個問題已經開始出現就在我已經添加了線程,當它在它的工作就好了一個進程中運行

+1

首先,在打開的文件中調用'fflush'是未定義的行爲......即使它沒有可怕的崩潰,它也不會做你想要的。誰教你使用'fflush'這樣的? –

+0

@R:好點!不過,我相信它會設置「errno」(EBADF?)。不確定它是否真的未定義。無論如何,我認爲這是一個真正的答案。 – jweyrich

+1

7.19.5.2:「如果流指向輸出流或未輸入最近操作的更新流,則fflush函數會將該流的所有未寫入數據傳遞到主機環境以寫入文件;否則,行爲是不確定的。「 –

回答

0

我會通過如果兩個fdopen()返回良好的價值觀,以及保釋檢查開始如果不。

1

點以下1可能是您的分段故障的真正原因:

  1. fgets追加空字符到存儲字符串的結尾。這意味着您必須通過MAXDATASIZE-1而不是MAXDATASIZE,否則可能會發生溢出。

  2. 有些人可能會聲稱你的程序正在泄漏內存,因爲你將fgets返回給rcvAux,它本身指向另一個手動分配的內存地址。在此作業之後,您將無法使用free,因爲分配的內存地址丟失。

  3. 您並未檢查socket()fdopen()的返回值。在退出應用程序之前,您沒有關閉sockfd

更新

正如在評論中指出的R..,在非可寫的文件描述符使用fflush是不確定的行爲。

您的代碼段不顯示任何connect()bind() + listen() + accept()要麼。您的套接字應首先連接以執行讀取和/或寫入操作。檢查每個操作的返回值會發現這一點。

+0

即使在可寫文件描述符中,如果處於「讀取模式」(如果最後的操作是讀取),則「fflush」就是UB。並且要在讀/寫之間切換,則需要介入的成功查找操作。 –

+0

嗯,對。所以如果保證fd上的最後一個操作是寫入,那麼只允許'fflush'。現在要走了,但稍後我會更新答案來提到這一點。再次感謝! :) – jweyrich

+0

或者如果該文件是新打開的或只是有一個成功的尋找(所以它既不讀也不寫)。重要的一點是,如果讀取有潛在的緩衝數據,則不允許使用「fflush」(您可以認爲其原因是「fflush」屬於寫入緩衝區,而緩衝區受讀取模式限制)。 –

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

上面創建了一個斷開連接 TCP套接字。

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

這些打開與兩個功能異常的FILE*相同的斷開連接的插座。

您需要兩個不同的連接套接字來啓動。

如果你發佈的代碼是一個完整的程序,我看不出它應該如何工作。閱讀器和書寫器都以fgets()開頭,應該永遠阻止它們,因爲不會有數據。

+1

+1這可能是主要問題... –