2014-10-08 71 views
0

我想在C中建立一個客戶端/服務器。我建立連接,然後我想發送一個用戶名和密碼到服務器,服務器必須回覆確認他已收到usr/pwd。問題是服務器和客戶端一遇到「寫入」或「讀取」功能就立即退出。我該怎麼辦?寫入套接字導致「程序退出代碼141」在C

server.c

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 
#include <arpa/inet.h> 
#include <sys/types.h> 
#include <netinet/in.h> 
#include <sys/socket.h> 
#include <netdb.h> 
#include <signal.h> 

void main(){ 
    int ds_sock; 
    struct sockaddr_in my_addr; 
    ds_sock=socket(AF_INET,SOCK_STREAM,0); 

    memset(&my_addr,0,sizeof(my_addr)); 
    my_addr.sin_family=AF_INET; 
    my_addr.sin_port=htons(25000); 
    my_addr.sin_addr.s_addr=INADDR_ANY; 

    if(bind(ds_sock,(struct sockaddr *)&my_addr,sizeof(my_addr))<0){ 
     printf("error in bind"); 
    } 

    listen(ds_sock,2); 
    int ds_sock_acc; 
    struct sockaddr_in addr; 
    size_t sin_size = sizeof(struct sockaddr_in); 
    signal(SIGCHLD,SIG_IGN); 
    while(1){ 
     if((ds_sock_acc=accept(ds_sock,(struct sockaddr *)&addr,&sin_size))<1){ 
      printf("error accept"); 
     } 
    printf("connected"); 
    char usr[10]; 
    read(ds_sock,usr,10); 
    char* confirm_usr; 
    confirm_usr="Username received"; 
    write(ds_sock,confirm_usr,100); 

    char pwd[10]; 
    read(ds_sock,pwd,10); 
    char* confirm_pwd; 
    confirm_pwd="Password received"; 
    write(ds_sock,confirm_pwd,100); 
    }  
} 

client.c:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 
#include <arpa/inet.h> 
#include <sys/types.h> 
#include <netinet/in.h> 
#include <sys/socket.h> 
#include <netdb.h> 

void main(){ 
    int ds_sock; 
    ds_sock = socket(AF_INET, SOCK_STREAM,0); 

    int ret; 
    struct sockaddr_in Eaddr; 
    Eaddr.sin_family = AF_INET; 
    Eaddr.sin_port = htons(25000); 
    Eaddr.sin_addr.s_addr=inet_addr("127.0.0.1"); 
    ret = connect(ds_sock,(struct sockaddr *)&Eaddr,sizeof(Eaddr)); 
    if(ret==-1){ 
     printf("error connect"); 
     exit(EXIT_FAILURE); 
    } 
    printf("connect OK"); 

    char usr[10]; 
    printf("Insert username"); 
    scanf("%s",usr); 

    char pwd[12]; 
    printf("Insert password"); 
    scanf("%s",pwd); 
    printf("%s",pwd); 

    write(ds_sock,usr,10); 
    char usr_reply[100]; 
    read(ds_sock,usr_reply,100); 
    printf("%s",usr_reply); 

    write(ds_sock,pwd,12); 
    char pwd_reply[100]; 
    read(ds_sock,pwd_reply,100); 
    printf("%s",pwd_reply); 
} 
+1

它是'int main(void)',隊友。 – Jens 2014-10-08 14:52:05

回答

2

你所訪問出界,從而引發在您的通話write()未定義行爲:

char* confirm_usr; 
confirm_usr="Username received"; 
write(ds_sock,confirm_usr,100); 

你'要求write()發送100個字節,但只提供一個指向18個字節的指針。從該位置讀取超過18個數字會觸發未定義的行爲。這將更有意義使用strlen()避免硬編碼的長度:

const char *confirm_usr = "Username received"; 
write(ds_sock, confirm_usr, strlen(confirm_usr) + 1); 

我把它+ 1實際發送終止'\0'字符數限制,否則另一端沒有搞清楚當字符串結束的方式。

此外,您必須檢查大量調用的返回值,I/O可以並將失敗,只需處理該問題。

這也很奇怪,它看起來好像服務器和客戶端都開始執行read(),並且服務器在不同於ds_sock_acc的套接字上執行I/O。

+0

感謝您的回答,我現在正在測試它。我在編寫客戶端代碼時犯了一個錯誤,現在就修復它!一旦我完成測試,會立即報告給您! :) – testermaster 2014-10-08 14:55:43

+0

無事可做。我已經完成了這些修復,但仍然存在問題。應該有另一個問題,因爲當客戶端打印「連接正常」時,服務器不打印「連接」:( – testermaster 2014-10-08 15:14:56

+0

「並且服務器在與ds_sock_acc不同的套接字上執行I/O。」這是解決方案!一個愚蠢的錯誤:(非常感謝你! – testermaster 2014-10-08 16:03:24

1

儘管第一個答案非常完整,但我想添加141錯誤是一個SIGPIPE錯誤。 (在linux手冊中查看) 您可以對程序進行比較以查找錯誤代碼或實現errno和perror。