2013-12-09 88 views
0

我正在寫一個客戶機 - 服務器C項目,服務器處理來自客戶機的消息,並將它們複製到備份服務器。它運行良好,但該項目(其大學項目)的其中一點是爲錯誤做好準備,在這種情況下 - 備份服務器正在死亡。C(Linux)檢查套接字

我有這個在我的複製功能:

int table_skel_replicate(struct message_t *msg, int sockSecundario){ 
    char *msg_buf; 
    int buf_size_net = 0; 
    int buf_size=0; 
    int okk; 

    struct sockaddr_in server; 

    msg->opcode--; 

    buf_size = message_to_buffer (msg, &msg_buf); 

    buf_size_net = htonl(buf_size); 

    okk = write(sockSecundario, &buf_size_net, sizeof(int)); 

    if(okk == -1 || okk == 0) { 
     msg->opcode++; 
     return okk; 
    } 

    okk = write_all (sockSecundario, msg_buf, buf_size); 

    if(okk == -1) { 
     msg->opcode++; 
     return okk; 
    } 

    okk = read (sockSecundario, &buf_size_net, sizeof(int)); 

    if(okk == -1 || okk == 0) { 
     msg->opcode++; 
     return okk; 
    } 

    buf_size = ntohl(buf_size_net); 
    msg_buf = malloc (buf_size); 

    okk = read_all(sockSecundario, msg_buf, buf_size); 

    msg->opcode++; 

    return okk; 
} 

它應該儘快備份服務器失敗死亡的第一write()。但它沒有。 相反,它處理write_all()函數(基本上while內部爲write()用於長傳輸),並在那裏首先執行write()。我試過使用checksockopt()函數,但它返回狀態爲OK ...

主應用程序簡單地關閉。任何幫助讚賞...

+2

您需要檢查每個**調用write()的錯誤,備份服務器可以在任何一對write()調用之間的任何時間死亡。確保你的代碼優雅地處理每一個可能的失敗。 –

+0

由於緩衝,寫入在另一端的連接斷開後可能成功。隨後的寫入最終會失敗。這就是爲什麼你需要檢查所有'write()'返回,而不僅僅是一個。 – EJP

+0

OP似乎也檢查他的'write'返回 - 大概在'write_all'中。問題在於,OP如何確定寫入失敗的原因。第一次寫入可能會成功,但會引發RST,然後是隨後的寫入將會因EPIPE而失敗。所以這可能是預期的行爲。 – Duck

回答

0

您的write()調用檢查大概是無效的,因爲該程序由於SIGPIPE而終止。 man 2 write

FD被連接到管道或插座,其讀出端是 封閉。當發生這種情況時,寫入過程也會收到一個信號,其中包括一個信號,即 SIGPIPE信號。 (由此,寫返回值被認爲是隻有當 程序捕獲,塊或忽略該信號。)

容易地避免這一點,代替每

write(sockSecundario, …, …) 

通過

send(sockSecundario, …, …, MSG_NOSIGNAL)