2017-02-01 121 views
0

我想創建一個客戶端並將其連接到服務器。我知道客戶端進程在服務器之前開始運行,所以我在無限循環中進行連接,直到它接受爲止。然後我想輸入消息給客戶端併發送給服務器,服務器會在屏幕上打印它們。我刪除了代碼中的所有錯誤檢測,使其更短,我知道他們必須在那裏。我試圖這樣做,但服務器收不到任何東西,客戶端不能做第二次連接。C posix套接字,無法將數據從客戶端發送到服務器

服務器

int main(int argc, char *argv[]) 
{ 
    int sockfd, newsockfd; 
    socklen_t clilen; 
    char buffer[256]; 
    struct sockaddr_in serv_addr, cli_addr; 
    sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    serv_addr.sin_family = AF_INET; 
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 
    serv_addr.sin_port = htons(5000); 
    bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)); 
    listen(sockfd, 5); 
    clilen = sizeof(cli_addr); 
    while (newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr,&clilen) >= 0) 
    { 
     read(newsockfd, buffer, 255); 
     close(newsockfd); 
    } 
    close(sockfd); 
    return 0; 
} 

客戶

int main(int argc, char *argv[]) 
    { 
    int sockfd; 
    struct sockaddr_in serv_addr; 

    char buffer[256]; 
    sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    serv_addr.sin_family = AF_INET; 
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 
    serv_addr.sin_port = htons(5000); 
    while (1) { 
     while ((connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)) { 
      printf("trying to connect\n"); 
      sleep(1); 
     } 
     printf("connected\nplease, enter a message\n"); 
     scanf("%s", buffer); 
     write(sockfd, buffer, strlen(buffer)); 
    } 
    close(sockfd); 
    return 0; 
} 
+0

一旦'connect()'失敗,就不能保證它可以在同一套接字上再次被調用。通常最好在每個connect()嘗試中銷燬並重新創建套接字。然而,無論哪種方式,一旦'connect()'成功,在下一次循環迭代中再次調用'connect()'之前,客戶端不會關閉連接的套接字。 –

+0

如果您從代碼中刪除所有錯誤處理,您怎麼可能期望能夠調試它?這不是一個合理的策略。在你提供一個錯誤代碼之前,它也不是一個可以回答的問題,直到你把錯誤處理回來,你才能這樣做。直到同上之前,您無法證明沒有錯誤代碼。 – EJP

回答

2

我不只是知道你是如何編譯你的代碼,但如果你已經設置了警示標誌(gcc中的-Wall)你會得到這個警告

server.c: In function ‘main’: 
server.c:33:44: warning: suggest parentheses around assignment used as truth value [-Wparentheses] 
if (newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr,&clilen) >= 0) { 

通過其代理,我變了,這個..

if (newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr,&clilen) >= 0) { 

要..(注意額外的括號)

if ((newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr,&clilen)) >= 0) { 

我沒有更多的額外的警告,並且服務器抓客戶的消息。

下面是在調試這個我跑的服務器(這基本上是有輕微的改變你的代碼)

int sockfd, newsockfd; 
socklen_t clilen; 
char buffer[256]; 
int nbytes = 0; 
struct sockaddr_in serv_addr, cli_addr; 
sockfd = socket(AF_INET, SOCK_STREAM, 0); 
serv_addr.sin_family = AF_INET; 
//serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 
serv_addr.sin_addr.s_addr = INADDR_ANY; 
serv_addr.sin_port = htons(5007); 
bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)); 


if (listen(sockfd, 5) <0) { } 

clilen = sizeof(cli_addr); 
if ((newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr,&clilen)) >= 0) { 

    while ((nbytes = read(newsockfd, buffer, sizeof(buffer)))<0) { 
     sleep(1); 
    } 

    printf("client sent: %s", buffer); 
} 
close(newsockfd); 
close(sockfd); 
return 0; 
0

另一個問題是,我們有我們每次做客戶端連接,如時間創建套接字:

while (1) { 
    sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    while ((connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)) { 
     printf("trying to connect\n"); 
     sleep(1); 
    } 
    printf("connected\nplease, enter a message\n"); 
    scanf("%s", buffer); 
    write(sockfd, buffer, strlen(buffer)); 
} 
+0

你應該只有一個套接字並重用它(除非你想同時連接到多個服務器點) 你也沒有正確地從while循環中斷,所以你將永遠沒有機會正確地關閉你的套接字。它會傷害你的測試,因爲你必須等待操作系統在你退出後釋放那個端口 – svarog

相關問題