2012-02-08 54 views
0

我想學習和理解BSD套接字編程使用這些簡單的示例C++代碼爲TCP-IP服務器和客戶端。我已經讀過像socket(),bind(),listen(),accept()和read/recv()這樣的標準API,甚至可以在g ++/Linux上編譯下面的代碼。簡單的套接字編程代碼工作

我想要做的是看到它在現實生活中的工作,我的意思是運行服務器代碼,然後使用客戶端連接到它並從客戶端到服務器發送數據,並反之亦然,並驗證收到的數據。所有這一切都在同一網段的兩個Linux盒子(Ubuntu)中。我有私人的IPv4地址給這兩臺Linux機器。

在上述網絡設置中,需要通過什麼設置來實現此目的,以及在下面的服務器和客戶端代碼中更改哪些代碼?我想真正看到它在網絡上實時工作?

還有任何進一步的指向代碼,博客文章學習動手套接字編程/網絡編程將有所幫助。

//TCP SERVER 
#include<sys/socket.h> 
#include<netinet/in.h> 
#include<stdio.h> 
#include<string.h> 
#include<stdlib.h> 
#include <arpa/inet.h> 
//#include <fcntl.h> 
#include <unistd.h> 

main() 
{ 
    char buf[100]; 
    socklen_t len; 
    int k,sock_desc,temp_sock_desc; 
    struct sockaddr_in client,server; 
    memset(&client,0,sizeof(client)); 
    memset(&server,0,sizeof(server)); 
    sock_desc = socket(AF_INET,SOCK_STREAM,0); 
    server.sin_family = AF_INET; server.sin_addr.s_addr = inet_addr("127.0.0.1"); 
    server.sin_port = 7777; 
    k = bind(sock_desc,(struct sockaddr*)&server,sizeof(server)); 
    k = listen(sock_desc,20); len = sizeof(client); 
    temp_sock_desc = accept(sock_desc,(struct sockaddr*)&client,&len); 
    while(1) 
    {  
     k = recv(temp_sock_desc,buf,100,0);  
     if(strcmp(buf,"exit")==0)   
      break;  
     if(k>0)   
      printf("%s",buf); 
    } close(sock_desc); 
    close(temp_sock_desc); 
    return 0; 
} 

//TCP CLIENT 
#include<sys/socket.h> 
#include<netinet/in.h> 
#include<stdio.h> 
#include<string.h> 
#include<stdlib.h> 
#include <arpa/inet.h> 
//#include <fcntl.h> 
#include <unistd.h> 

main() 
{ 
    char buf[100]; 
    struct sockaddr_in client; 
    int sock_desc,k; 
    sock_desc = socket(AF_INET,SOCK_STREAM,0); 
    memset(&client,0,sizeof(client)); 
    client.sin_family = AF_INET; 
    client.sin_addr.s_addr = inet_addr("127.0.0.1"); 
    client.sin_port = 7777; 
    k = connect(sock_desc,(struct sockaddr*)&client,sizeof(client)); 
    while(1) 
    {  
     gets(buf);  
     k = send(sock_desc,buf,100,0);  
     if(strcmp(buf,"exit")==0)   
      break; 
    } 
    close(sock_desc); 
    return 0; 
} 
+0

那麼你嘗試了什麼,發生了什麼? – Useless 2012-02-08 17:45:47

+0

這是你能找到的最簡單的例子嗎? – Beta 2012-02-08 17:45:59

+0

@Useless我在Linux終端上將服務器代碼作爲可執行文件執行。在同一個盒子的另一個終端上,我執行了客戶端代碼。在客戶端可執行的終端窗口上鍵入一些內容。沒有在服務器上收到任何信息。這就是我想了解的數據流如何在這些套接字代碼示例中發生。 – goldenmean 2012-02-08 17:48:39

回答

2

在服務器端,您需要將地址127.0.0.1更改爲0.0.0.0以啓用任何位置的連接。您也可以使用telnet而不是客戶端代碼,因此請檢查服務器是否按預期工作。還要調查您的各種Linux上是否有snoop命令。

在客戶端需要使用服務器裝置

+0

嘗試在更改下,但看不到任何正在建立的連接/ data trasnfer 1]將服務器代碼套接字IP地址更改爲0.0.0.0。建立。執行。然後從另一個終端嘗試SSH(telnet在Linux PC上被阻止)。當你說使用telnet時,你的意思是什麼。 2]還將客戶端代碼套接字地址更改爲執行服務器代碼的實際私有IP地址。同樣的行爲沒有轉移或連接發生,我可以看到。我誤解了一些東西嗎?這個例子中使用的端口號是否可能是問題? – goldenmean 2012-02-08 18:01:03

2

你需要做以下修改的IP地址。

端口號 - 使用htons

服務器 - server.sin_port = htons(7777); 客戶端 - client.sin_port = htons(7777);

服務器 - 得到它從任何地址接收 - 即server.sin_addr.s_addr = INADDR_ANY;

希望幫助有些

4

添加一些錯誤處理到你的代碼,這可能會掩蓋一些東西,例如:

服務器:

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

main() 
{ 
    int sock_desc = socket(AF_INET, SOCK_STREAM, 0); 
    if (sock_desc == -1) 
    { 
     printf("cannot create socket!\n"); 
     return 0; 
    } 

    struct sockaddr_in server; 
    memset(&server, 0, sizeof(server)); 
    server.sin_family = AF_INET; 
    server.sin_addr.s_addr = INADDR_ANY; 
    server.sin_port = htons(7777); 
    if (bind(sock_desc, (struct sockaddr*)&server, sizeof(server)) != 0) 
    { 
     printf("cannot bind socket!\n"); 
     close(sock_desc); 
     return 0; 
    } 

    if (listen(sock_desc, 20) != 0) 
    { 
     printf("cannot listen on socket!\n"); 
     close(sock_desc); 
     return 0; 
    } 

    struct sockaddr_in client; 
    memset(&client, 0, sizeof(client)); 
    socklen_t len = sizeof(client); 
    int temp_sock_desc = accept(sock_desc, (struct sockaddr*)&client, &len); 
    if (temp_sock_desc == -1) 
    { 
     printf("cannot accept client!\n"); 
     close(sock_desc); 
     return 0; 
    } 

    char buf[100]; 
    int k; 

    while(1) 
    {  
     k = recv(temp_sock_desc, buf, 100, 0);  
     if (recv == -1) 
     { 
      printf("\ncannot read from client!\n"); 
      break; 
     } 

     if (recv == 0) 
     { 
      printf("\nclient disconnected.\n"); 
      break; 
     } 

     if (k > 0)   
      printf("%*.*s", k, k, buf); 

     if (strcmp(buf, "exit") == 0)   
      break;  
    } 

    close(temp_sock_desc); 
    close(sock_desc); 

    printf("server disconnected\n"); 
    return 0; 
} 

客戶:

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

main() 
{ 
    int sock_desc = socket(AF_INET, SOCK_STREAM, 0); 
    if (sock_desc == -1) 
    { 
     printf("cannot create socket!\n"); 
     return 0; 
    } 

    struct sockaddr_in client; 
    memset(&client, 0, sizeof(client)); 
    client.sin_family = AF_INET; 
    client.sin_addr.s_addr = inet_addr("127.0.0.1"); 
    client.sin_port = htons(7777); 

    if (connect(sock_desc, (struct sockaddr*)&client, sizeof(client)) != 0) 
    { 
     printf("cannot connect to server!\n"); 
     close(sock_desc); 
    } 

    char buf[100]; 
    char c = '\n'; 
    char *p_buf; 
    int k, len; 

    while(1) 
    {  
     gets(buf); 

     len = strlen(buf); 
     p_buf = buf; 

     while (len > 0) 
     { 
      k = send(sock_desc, p_buf, len, 0);  
      if (k == -1) 
      { 
       printf("cannot write to server!\n"); 
       break; 
      } 

      p_buf += k; 
      len -= k; 
     } 

     k = send(sock_desc, &c, 1, 0);  
     if (k == -1) 
     { 
      printf("cannot write to server!\n"); 
      break; 
     } 

     if (strcmp(buf, "exit") == 0)   
      break; 
    } 

    close(sock_desc); 
    printf("client disconnected\n"); 

    return 0; 
} 
+0

當從send()或recv()返回-1時,您應該始終檢查errno是否設置爲EINTR,如果是,則重複相同的調用。否則,您可能因中斷而導致無法解釋的故障。 – 2014-01-03 19:35:44

+0

這也適用於'accept()'和'connect()'。 – 2014-01-04 09:54:08

+0

不錯的示例代碼!謝謝雷米!我可以從你的編碼風格中學到很多東西 – 2015-04-21 08:49:47

0

它應該是這樣的。

if (connect(sock_desc, (struct sockaddr*)&client, sizeof(client)) != 0)