Linux网络编程 - BSD Socket网络通信编程



TCP通信编程流程


首先,服务器端需要做以下准备工作:
(1)调用socket()函数。建立socket对象,指定通信协议。
(2)调用bind()函数。将创建的socket对象与当前主机的某一个IP地和端口绑定。
(3)调用listen()函数。使socket对象处于监听状态,并设置监听队列大小。
客户端需要做以下准备工作:
(1)调用socket()函数。建立socket()对象,指定相同通信协议。
(2)应用程序可以显式的调用bind()函数为其绑定IP地址和端口,当然,也可以将这工作交给TCP/IP协议栈。
接着建立通信连接:
(1)客户端调用connect()函数。向服务器端发出连接请求。
(2)服务端监听到该请求,调用accept()函数接受请求,从而建立连接,并返回一个新的socket文件描述符专门处理该连接。
然后通信双方发送/接收数据:
(1)服务器端调用write()或send()函数发送数据,客户端调用read()或者recv()函数接收数据。反之客户端发送数据,服务器端接收数据。
(2)通信完成后,通信双方都需要调用close()或者shutdown()函数关闭socket对象。 

Socket网络编程API

创建socket对象


第一个参数用来指明socket对象所使用的地址簇或者协议簇


第二个参数为socket的类型


第三个参数标识采用协议簇中的哪一种协议,如果为0,则让系统自动选择默认协议,但原始套接口需要指定具体的协议。

绑定本地IP地址与端口bind

第二个参数是一个指向sockaddr结构的指针。 struct sockaddr只是提供地址类型规范,根据不同的应用,sockaddr需要选用不同的类型。struct sockaddr结构定义如下:

struct sockaddr结构

struct sockaddr结构只是提供简单的地址类型规范,根据不同的引用,struct sockaddr结构需要选用不同的类型,如下所述:

如果是UNIX域套接字,即本机通信的套接字,struct sockaddr结构选用以下定义


如果是IPv4网络通信,则地址结构体定义-- IPV4 


端口号

关于端口号Linux操作系统在文件/etc/services中进行了详细定义,小于1024的端口号为系统保留,用户应用程序不能随便使用。其文件部分内容如下:


IP地址

完成此步,该socket拥有了本地IP地址,端口,通信协议,不能接收客户端的请求,但可以向服务器发起连接。

监听网络listen


第一个参数是绑定了IP及端口信息的socket文件描述符。
第二个参数为请求排队的最大长度。当有多个客户端程序和服务器端相连时, 此值表示可以使用的处于等待的队列长度。
listen 函数将绑定的socket文件描述符变为监听套接字,完成此步: 服务器已经准备接收客户端连接请求了。

客户端发起连接connect


其第一个参数为socket返回的文件描述符。
第二个参数储存了服务器端的地址(包括服务器的IP地址和端口信息)。
第三个参数为该地址的长度。
如果执行成功,此函数将与地址为addr的服务器建立连接,并返回0,如果失败则返回-1。
正确完成此步:客户端socket拥有了目的IP,端口信息。

服务器接收连接accept

第一个参数是监听网络后的socket文件描述符。
第二参数为struct sockaddr 类型的地址空间首地址,第三个参数为该段地址空间长度,因此第二个参数用来存储客户端的IP地址和端口信息,以便为客户端返回数据。
需要注意的是,如果执行成功,此函数将返回一个新的文件描述符以标识该连接,从而使原来的文件描述符可以继续等待新的连接,这样便可以实现多客户端。如果执行失败,将返回-1。
至此,两端的连接已经建立,而服务器端又是如何区别多个连接的呢?

服务器端又是如何区别多个连接

对于任何一个TCP连接,最重要的信息包括源IP:源端口,目的IP:目的端口四个信息。例如,客户机192.168.0.10/24的3000、4000两端口同时向服务器192.168.0.100/24的80端口发起两个连接,在服务器端是如何区别两个连接的呢?


读写socket对象


TCP发送接收数据


第一个参数为发送的目标socket对象;
第二个参数为欲发送的数据位置;
第三个参数为数据的大小;
第四个参数操作flags,支持的值为0或MSG_OOB(发送带外数据)等。对套接字调用write()的行为与将flags设置为0的send()的行为完全相同。
如果执行成功,此函数将返回发送数据的大小,如果失败,将返回-1。

关闭socket对象


howto=0 这个时候系统会关闭读通道,但是可以继续往socket描述符中写。
howto=1 关闭写通道,和上面相反,此时只可以读。
howto=2 关闭读写通道,和close一样,在多进程程序里,当几个子进程共享一个套接字时,如果使用shutdown,那么所有的子进程都将不能操作,这时只能使用close()函数来关闭子进程的套接字描述符。

获取socket本地及对端信息

getsockname()将获取一个套接字的本地地址。

getpeername()将获取一个已经连接上的套接字的远程信息。

使用TCP实现简单的聊天程序

服务器端代码

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. #include <stdio.h>  
  2.   
  3. #include <stdlib.h>  
  4.   
  5. #include <errno.h>  
  6.   
  7. #include <string.h>  
  8.   
  9. #include <sys/types.h>  
  10.   
  11. #include <netinet/in.h>  
  12.   
  13. #include <sys/socket.h>  
  14.   
  15. #include <sys/wait.h>  
  16.   
  17. #include <unistd.h>  
  18.   
  19. #include <arpa/inet.h>  
  20.   
  21.   
  22.   
  23. #define MAXBUF 1024  
  24.   
  25.   
  26.   
  27. int main(int argc, char *argv[])  
  28.   
  29. {  
  30.   
  31.     int pid;      
  32.   
  33.     int sockfd, new_fd;  
  34.   
  35.     socklen_t len;  
  36.   
  37.     struct sockaddr_in my_addr, their_addr;  
  38.   
  39.     unsigned int myport, lisnum;  
  40.   
  41.     char buf[MAXBUF + 1];  
  42.   
  43.   
  44.   
  45.     if (argv[2])  
  46.   
  47.         myport = atoi(argv[2]);  
  48.   
  49.     else  
  50.   
  51.         myport = 7575;  
  52.   
  53.   
  54.   
  55.     if (argv[3])  
  56.   
  57.         lisnum = atoi(argv[3]);  
  58.   
  59.     else  
  60.   
  61.         lisnum = 5;  
  62.   
  63.   
  64.   
  65.     if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)   
  66.   
  67.     {  
  68.   
  69.         perror("socket");  
  70.   
  71.         exit(EXIT_FAILURE);  
  72.   
  73.     }  
  74.   
  75.       
  76.   
  77.     bzero(&my_addr, sizeof(my_addr));  
  78.   
  79.     my_addr.sin_family = AF_INET;  
  80.   
  81.     my_addr.sin_port = htons(myport);  
  82.   
  83.     if (argv[1])  
  84.   
  85.         my_addr.sin_addr.s_addr = inet_addr(argv[1]);  
  86.   
  87.     else  
  88.   
  89.         my_addr.sin_addr.s_addr = INADDR_ANY;  
  90.   
  91.   
  92.   
  93.     if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr))== -1)   
  94.   
  95.     {  
  96.   
  97.         perror("bind");  
  98.   
  99.         exit(EXIT_FAILURE);  
  100.   
  101.     }  
  102.   
  103.   
  104.   
  105.     if (listen(sockfd,lisnum ) == -1)   
  106.   
  107.     {  
  108.   
  109.         perror("listen");  
  110.   
  111.         exit(EXIT_FAILURE);  
  112.   
  113.     }  
  114.   
  115.     printf("wait for connect\n");     
  116.   
  117.     len = sizeof(struct sockaddr);  
  118.   
  119.     if ((new_fd =accept(sockfd, (struct sockaddr *) &their_addr,&len)) == -1)   
  120.   
  121.     {  
  122.   
  123.         perror("accept");  
  124.   
  125.         exit(EXIT_FAILURE);  
  126.   
  127.     }   
  128.   
  129.     else  
  130.   
  131.         printf("server: got connection from %s, port %d, socket %d\n",inet_ntoa(their_addr.sin_addr),ntohs(their_addr.sin_port), new_fd);  
  132.   
  133.         
  134.   
  135.     if(-1==(pid=fork()))      
  136.   
  137.     {  
  138.   
  139.         perror("fork");exit(EXIT_FAILURE);  
  140.   
  141.     }  
  142.   
  143.     else if( pid == 0)  
  144.   
  145.     {  
  146.   
  147.         while (1)   
  148.   
  149.         {  
  150.   
  151.             bzero(buf, MAXBUF + 1);  
  152.   
  153.             printf("input the message to send:");  
  154.   
  155.             fgets(buf, MAXBUF, stdin);  
  156.   
  157.             if (!strncasecmp(buf, "quit", 4))   
  158.   
  159.             {  
  160.   
  161.                 printf("i will close the connect!\n");  
  162.   
  163.                 break;  
  164.   
  165.             }  
  166.   
  167.             len = send(new_fd, buf, strlen(buf) - 1, 0);  
  168.   
  169.             if (len < 0)  
  170.   
  171.              {  
  172.   
  173.                 printf("message'%s' send failure!errno code is %d,errno message is '%s'\n",  
  174.   
  175.                 buf, errno, strerror(errno));  
  176.   
  177.                 break;  
  178.   
  179.             }  
  180.   
  181.         }  
  182.   
  183.     }  
  184.   
  185.     else   
  186.   
  187.     {     
  188.   
  189.         while(1)  
  190.   
  191.         {  
  192.   
  193.             bzero(buf, MAXBUF + 1);  
  194.   
  195.             len = recv(new_fd, buf, MAXBUF, 0);  
  196.   
  197.             if (len > 0)  
  198.   
  199.                 printf("message recv successful :'%s',%dByte recv\n",buf, len);  
  200.   
  201.             else if (len < 0)  
  202.   
  203.             {  
  204.   
  205.                 printf("recv failure!errno code is %d,errno message is '%s'\n",  
  206.   
  207.                 errno, strerror(errno));  
  208.   
  209.                 break;  
  210.   
  211.             }  
  212.   
  213.             else  
  214.   
  215.             {  
  216.   
  217.                 printf("the other one close quit\n");  
  218.   
  219.                 break;  
  220.   
  221.             }  
  222.   
  223.         }  
  224.   
  225.     }  
  226.   
  227.     close(new_fd);  
  228.   
  229.     close(sockfd);  
  230.   
  231.         return 0;  
  232.   
  233. }  

客户端代码

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. #include <stdio.h>  
  2.   
  3. #include <string.h>  
  4.   
  5. #include <errno.h>  
  6.   
  7. #include <sys/socket.h>  
  8.   
  9. #include <resolv.h>  
  10.   
  11. #include <stdlib.h>  
  12.   
  13. #include <netinet/in.h>  
  14.   
  15. #include <arpa/inet.h>  
  16.   
  17. #include <unistd.h>  
  18.   
  19.   
  20.   
  21. #define MAXBUF 1024  
  22.   
  23.   
  24.   
  25. int main(int argc, char **argv)  
  26.   
  27. {  
  28.   
  29.     int sockfd, len;  
  30.   
  31.     struct sockaddr_in dest;  
  32.   
  33.     char buffer[MAXBUF + 1];  
  34.   
  35.     if (argc != 3)   
  36.   
  37.     {  
  38.   
  39.         printf(" error format,it must be:\n\t\t%s IP port\n",argv[0]);  
  40.   
  41.         exit(EXIT_FAILURE);  
  42.   
  43.     }  
  44.   
  45.   
  46.   
  47.     if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {  
  48.   
  49.         perror("Socket");  
  50.   
  51.         exit(errno);  
  52.   
  53.     }  
  54.   
  55.     printf("socket created\n");  
  56.   
  57.   
  58.   
  59.   
  60.   
  61.     bzero(&dest, sizeof(dest));  
  62.   
  63.     dest.sin_family = AF_INET;  
  64.   
  65.     dest.sin_port = htons(atoi(argv[2]));  
  66.   
  67.     if (inet_aton(argv[1], (struct in_addr *) &dest.sin_addr.s_addr) == 0)   
  68.   
  69.     {  
  70.   
  71.         perror(argv[1]);    exit(errno);  
  72.   
  73.     }  
  74.   
  75.     if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest))==-1)   
  76.   
  77.     {  
  78.   
  79.         perror("Connect ");  
  80.   
  81.         exit(errno);  
  82.   
  83.     }  
  84.   
  85.     printf("server connected\n");  
  86.   
  87.   
  88.   
  89.     pid_t pid;  
  90.   
  91.     if(-1==(pid=fork()))  
  92.   
  93.     {  
  94.   
  95.         perror("fork");exit(EXIT_FAILURE);  
  96.   
  97.     }  
  98.   
  99.     else if (pid==0)  
  100.   
  101.     {  
  102.   
  103.         while (1)   
  104.   
  105.         {  
  106.   
  107.             bzero(buffer, MAXBUF + 1);  
  108.   
  109.             len = recv(sockfd, buffer, MAXBUF, 0);  
  110.   
  111.             if (len > 0)  
  112.   
  113.                 printf("recv successful:'%s',%d byte recv\n",buffer, len);  
  114.   
  115.             else if(len < 0)  
  116.   
  117.             {  
  118.   
  119.                 perror("recv");  
  120.   
  121.                 break;  
  122.   
  123.             }  
  124.   
  125.             else  
  126.   
  127.             {  
  128.   
  129.                 printf("the other one close ,quit\n");  
  130.   
  131.                 break;  
  132.   
  133.             }  
  134.   
  135.         }     
  136.   
  137.     }  
  138.   
  139.     else  
  140.   
  141.     {  
  142.   
  143.         while (1)   
  144.   
  145.         {  
  146.   
  147.             bzero(buffer, MAXBUF + 1);  
  148.   
  149.             printf("pls send message to send:");  
  150.   
  151.             fgets(buffer, MAXBUF, stdin);  
  152.   
  153.             if (!strncasecmp(buffer, "quit", 4))   
  154.   
  155.             {  
  156.   
  157.                 printf(" i will quit!\n");  
  158.   
  159.                 break;  
  160.   
  161.             }  
  162.   
  163.             len = send(sockfd, buffer, strlen(buffer) - 1, 0);  
  164.   
  165.             if (len < 0)   
  166.   
  167.             {  
  168.   
  169.                 perror("send");  
  170.   
  171.                 break;  
  172.   
  173.             }  
  174.   
  175.         }  
  176.   
  177.     }  
  178.   
  179.     close(sockfd);  
  180.   
  181.     return 0;  
  182.   
  183. }  

服务器端运行结果

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. $ ./tcp_p_p_chat_server 172.18.229.62 7576 5  
  2. wait for connect  
  3. server: got connection from 172.18.229.62, port 60199, socket 4  
  4. input the message to send:hello  
  5. input the message to send:message recv successful :'hi',2Byte recv  
  6.   
  7. input the message to send:  
  8. input the message to send:quit  
  9. i will close the connect!<span style="color:#339999;">  
  10. </span>  

客户端运行结果

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. $ ./tcp_p_p_chat_client 172.18.229.62 7576   
  2. socket created  
  3. server connected  
  4. pls send message to send:recv successful:'hello',5 byte recv  
  5. hi  
  6. pls send message to send:quit  
  7.  i will quit!<span style="color:#339999;">  
  8. </span>  

原文链接

http://blog.csdn.net/geng823/article/details/41748819

TCP通信编程流程


首先,服务器端需要做以下准备工作:
(1)调用socket()函数。建立socket对象,指定通信协议。
(2)调用bind()函数。将创建的socket对象与当前主机的某一个IP地和端口绑定。
(3)调用listen()函数。使socket对象处于监听状态,并设置监听队列大小。
客户端需要做以下准备工作:
(1)调用socket()函数。建立socket()对象,指定相同通信协议。
(2)应用程序可以显式的调用bind()函数为其绑定IP地址和端口,当然,也可以将这工作交给TCP/IP协议栈。
接着建立通信连接:
(1)客户端调用connect()函数。向服务器端发出连接请求。
(2)服务端监听到该请求,调用accept()函数接受请求,从而建立连接,并返回一个新的socket文件描述符专门处理该连接。
然后通信双方发送/接收数据:
(1)服务器端调用write()或send()函数发送数据,客户端调用read()或者recv()函数接收数据。反之客户端发送数据,服务器端接收数据。
(2)通信完成后,通信双方都需要调用close()或者shutdown()函数关闭socket对象。 

Socket网络编程API

创建socket对象


第一个参数用来指明socket对象所使用的地址簇或者协议簇


第二个参数为socket的类型


第三个参数标识采用协议簇中的哪一种协议,如果为0,则让系统自动选择默认协议,但原始套接口需要指定具体的协议。

绑定本地IP地址与端口bind

第二个参数是一个指向sockaddr结构的指针。 struct sockaddr只是提供地址类型规范,根据不同的应用,sockaddr需要选用不同的类型。struct sockaddr结构定义如下:

struct sockaddr结构

struct sockaddr结构只是提供简单的地址类型规范,根据不同的引用,struct sockaddr结构需要选用不同的类型,如下所述:

如果是UNIX域套接字,即本机通信的套接字,struct sockaddr结构选用以下定义


如果是IPv4网络通信,则地址结构体定义-- IPV4 


端口号

关于端口号Linux操作系统在文件/etc/services中进行了详细定义,小于1024的端口号为系统保留,用户应用程序不能随便使用。其文件部分内容如下:


IP地址

完成此步,该socket拥有了本地IP地址,端口,通信协议,不能接收客户端的请求,但可以向服务器发起连接。

监听网络listen


第一个参数是绑定了IP及端口信息的socket文件描述符。
第二个参数为请求排队的最大长度。当有多个客户端程序和服务器端相连时, 此值表示可以使用的处于等待的队列长度。
listen 函数将绑定的socket文件描述符变为监听套接字,完成此步: 服务器已经准备接收客户端连接请求了。

客户端发起连接connect


其第一个参数为socket返回的文件描述符。
第二个参数储存了服务器端的地址(包括服务器的IP地址和端口信息)。
第三个参数为该地址的长度。
如果执行成功,此函数将与地址为addr的服务器建立连接,并返回0,如果失败则返回-1。
正确完成此步:客户端socket拥有了目的IP,端口信息。

服务器接收连接accept

第一个参数是监听网络后的socket文件描述符。
第二参数为struct sockaddr 类型的地址空间首地址,第三个参数为该段地址空间长度,因此第二个参数用来存储客户端的IP地址和端口信息,以便为客户端返回数据。
需要注意的是,如果执行成功,此函数将返回一个新的文件描述符以标识该连接,从而使原来的文件描述符可以继续等待新的连接,这样便可以实现多客户端。如果执行失败,将返回-1。
至此,两端的连接已经建立,而服务器端又是如何区别多个连接的呢?

服务器端又是如何区别多个连接

对于任何一个TCP连接,最重要的信息包括源IP:源端口,目的IP:目的端口四个信息。例如,客户机192.168.0.10/24的3000、4000两端口同时向服务器192.168.0.100/24的80端口发起两个连接,在服务器端是如何区别两个连接的呢?


读写socket对象


TCP发送接收数据


第一个参数为发送的目标socket对象;
第二个参数为欲发送的数据位置;
第三个参数为数据的大小;
第四个参数操作flags,支持的值为0或MSG_OOB(发送带外数据)等。对套接字调用write()的行为与将flags设置为0的send()的行为完全相同。
如果执行成功,此函数将返回发送数据的大小,如果失败,将返回-1。

关闭socket对象


howto=0 这个时候系统会关闭读通道,但是可以继续往socket描述符中写。
howto=1 关闭写通道,和上面相反,此时只可以读。
howto=2 关闭读写通道,和close一样,在多进程程序里,当几个子进程共享一个套接字时,如果使用shutdown,那么所有的子进程都将不能操作,这时只能使用close()函数来关闭子进程的套接字描述符。

获取socket本地及对端信息

getsockname()将获取一个套接字的本地地址。

getpeername()将获取一个已经连接上的套接字的远程信息。

使用TCP实现简单的聊天程序

服务器端代码

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. #include <stdio.h>  
  2.   
  3. #include <stdlib.h>  
  4.   
  5. #include <errno.h>  
  6.   
  7. #include <string.h>  
  8.   
  9. #include <sys/types.h>  
  10.   
  11. #include <netinet/in.h>  
  12.   
  13. #include <sys/socket.h>  
  14.   
  15. #include <sys/wait.h>  
  16.   
  17. #include <unistd.h>  
  18.   
  19. #include <arpa/inet.h>  
  20.   
  21.   
  22.   
  23. #define MAXBUF 1024  
  24.   
  25.   
  26.   
  27. int main(int argc, char *argv[])  
  28.   
  29. {  
  30.   
  31.     int pid;      
  32.   
  33.     int sockfd, new_fd;  
  34.   
  35.     socklen_t len;  
  36.   
  37.     struct sockaddr_in my_addr, their_addr;  
  38.   
  39.     unsigned int myport, lisnum;  
  40.   
  41.     char buf[MAXBUF + 1];  
  42.   
  43.   
  44.   
  45.     if (argv[2])  
  46.   
  47.         myport = atoi(argv[2]);  
  48.   
  49.     else  
  50.   
  51.         myport = 7575;  
  52.   
  53.   
  54.   
  55.     if (argv[3])  
  56.   
  57.         lisnum = atoi(argv[3]);  
  58.   
  59.     else  
  60.   
  61.         lisnum = 5;  
  62.   
  63.   
  64.   
  65.     if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)   
  66.   
  67.     {  
  68.   
  69.         perror("socket");  
  70.   
  71.         exit(EXIT_FAILURE);  
  72.   
  73.     }  
  74.   
  75.       
  76.   
  77.     bzero(&my_addr, sizeof(my_addr));  
  78.   
  79.     my_addr.sin_family = AF_INET;  
  80.   
  81.     my_addr.sin_port = htons(myport);  
  82.   
  83.     if (argv[1])  
  84.   
  85.         my_addr.sin_addr.s_addr = inet_addr(argv[1]);  
  86.   
  87.     else  
  88.   
  89.         my_addr.sin_addr.s_addr = INADDR_ANY;  
  90.   
  91.   
  92.   
  93.     if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr))== -1)   
  94.   
  95.     {  
  96.   
  97.         perror("bind");  
  98.   
  99.         exit(EXIT_FAILURE);  
  100.   
  101.     }  
  102.   
  103.   
  104.   
  105.     if (listen(sockfd,lisnum ) == -1)   
  106.   
  107.     {  
  108.   
  109.         perror("listen");  
  110.   
  111.         exit(EXIT_FAILURE);  
  112.   
  113.     }  
  114.   
  115.     printf("wait for connect\n");     
  116.   
  117.     len = sizeof(struct sockaddr);  
  118.   
  119.     if ((new_fd =accept(sockfd, (struct sockaddr *) &their_addr,&len)) == -1)   
  120.   
  121.     {  
  122.   
  123.         perror("accept");  
  124.   
  125.         exit(EXIT_FAILURE);  
  126.   
  127.     }   
  128.   
  129.     else  
  130.   
  131.         printf("server: got connection from %s, port %d, socket %d\n",inet_ntoa(their_addr.sin_addr),ntohs(their_addr.sin_port), new_fd);  
  132.   
  133.         
  134.   
  135.     if(-1==(pid=fork()))      
  136.   
  137.     {  
  138.   
  139.         perror("fork");exit(EXIT_FAILURE);  
  140.   
  141.     }  
  142.   
  143.     else if( pid == 0)  
  144.   
  145.     {  
  146.   
  147.         while (1)   
  148.   
  149.         {  
  150.   
  151.             bzero(buf, MAXBUF + 1);  
  152.   
  153.             printf("input the message to send:");  
  154.   
  155.             fgets(buf, MAXBUF, stdin);  
  156.   
  157.             if (!strncasecmp(buf, "quit", 4))   
  158.   
  159.             {  
  160.   
  161.                 printf("i will close the connect!\n");  
  162.   
  163.                 break;  
  164.   
  165.             }  
  166.   
  167.             len = send(new_fd, buf, strlen(buf) - 1, 0);  
  168.   
  169.             if (len < 0)  
  170.   
  171.              {  
  172.   
  173.                 printf("message'%s' send failure!errno code is %d,errno message is '%s'\n",  
  174.   
  175.                 buf, errno, strerror(errno));  
  176.   
  177.                 break;  
  178.   
  179.             }  
  180.   
  181.         }  
  182.   
  183.     }  
  184.   
  185.     else   
  186.   
  187.     {     
  188.   
  189.         while(1)  
  190.   
  191.         {  
  192.   
  193.             bzero(buf, MAXBUF + 1);  
  194.   
  195.             len = recv(new_fd, buf, MAXBUF, 0);  
  196.   
  197.             if (len > 0)  
  198.   
  199.                 printf("message recv successful :'%s',%dByte recv\n",buf, len);  
  200.   
  201.             else if (len < 0)  
  202.   
  203.             {  
  204.   
  205.                 printf("recv failure!errno code is %d,errno message is '%s'\n",  
  206.   
  207.                 errno, strerror(errno));  
  208.   
  209.                 break;  
  210.   
  211.             }  
  212.   
  213.             else  
  214.   
  215.             {  
  216.   
  217.                 printf("the other one close quit\n");  
  218.   
  219.                 break;  
  220.   
  221.             }  
  222.   
  223.         }  
  224.   
  225.     }  
  226.   
  227.     close(new_fd);  
  228.   
  229.     close(sockfd);  
  230.   
  231.         return 0;  
  232.   
  233. }  

客户端代码

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. #include <stdio.h>  
  2.   
  3. #include <string.h>  
  4.   
  5. #include <errno.h>  
  6.   
  7. #include <sys/socket.h>  
  8.   
  9. #include <resolv.h>  
  10.   
  11. #include <stdlib.h>  
  12.   
  13. #include <netinet/in.h>  
  14.   
  15. #include <arpa/inet.h>  
  16.   
  17. #include <unistd.h>  
  18.   
  19.   
  20.   
  21. #define MAXBUF 1024  
  22.   
  23.   
  24.   
  25. int main(int argc, char **argv)  
  26.   
  27. {  
  28.   
  29.     int sockfd, len;  
  30.   
  31.     struct sockaddr_in dest;  
  32.   
  33.     char buffer[MAXBUF + 1];  
  34.   
  35.     if (argc != 3)   
  36.   
  37.     {  
  38.   
  39.         printf(" error format,it must be:\n\t\t%s IP port\n",argv[0]);  
  40.   
  41.         exit(EXIT_FAILURE);  
  42.   
  43.     }  
  44.   
  45.   
  46.   
  47.     if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {  
  48.   
  49.         perror("Socket");  
  50.   
  51.         exit(errno);  
  52.   
  53.     }  
  54.   
  55.     printf("socket created\n");  
  56.   
  57.   
  58.   
  59.   
  60.   
  61.     bzero(&dest, sizeof(dest));  
  62.   
  63.     dest.sin_family = AF_INET;  
  64.   
  65.     dest.sin_port = htons(atoi(argv[2]));  
  66.   
  67.     if (inet_aton(argv[1], (struct in_addr *) &dest.sin_addr.s_addr) == 0)   
  68.   
  69.     {  
  70.   
  71.         perror(argv[1]);    exit(errno);  
  72.   
  73.     }  
  74.   
  75.     if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest))==-1)   
  76.   
  77.     {  
  78.   
  79.         perror("Connect ");  
  80.   
  81.         exit(errno);  
  82.   
  83.     }  
  84.   
  85.     printf("server connected\n");  
  86.   
  87.   
  88.   
  89.     pid_t pid;  
  90.   
  91.     if(-1==(pid=fork()))  
  92.   
  93.     {  
  94.   
  95.         perror("fork");exit(EXIT_FAILURE);  
  96.   
  97.     }  
  98.   
  99.     else if (pid==0)  
  100.   
  101.     {  
  102.   
  103.         while (1)   
  104.   
  105.         {  
  106.   
  107.             bzero(buffer, MAXBUF + 1);  
  108.   
  109.             len = recv(sockfd, buffer, MAXBUF, 0);  
  110.   
  111.             if (len > 0)  
  112.   
  113.                 printf("recv successful:'%s',%d byte recv\n",buffer, len);  
  114.   
  115.             else if(len < 0)  
  116.   
  117.             {  
  118.   
  119.                 perror("recv");  
  120.   
  121.                 break;  
  122.   
  123.             }  
  124.   
  125.             else  
  126.   
  127.             {  
  128.   
  129.                 printf("the other one close ,quit\n");  
  130.   
  131.                 break;  
  132.   
  133.             }  
  134.   
  135.         }     
  136.   
  137.     }  
  138.   
  139.     else  
  140.   
  141.     {  
  142.   
  143.         while (1)   
  144.   
  145.         {  
  146.   
  147.             bzero(buffer, MAXBUF + 1);  
  148.   
  149.             printf("pls send message to send:");  
  150.   
  151.             fgets(buffer, MAXBUF, stdin);  
  152.   
  153.             if (!strncasecmp(buffer, "quit", 4))   
  154.   
  155.             {  
  156.   
  157.                 printf(" i will quit!\n");  
  158.   
  159.                 break;  
  160.   
  161.             }  
  162.   
  163.             len = send(sockfd, buffer, strlen(buffer) - 1, 0);  
  164.   
  165.             if (len < 0)   
  166.   
  167.             {  
  168.   
  169.                 perror("send");  
  170.   
  171.                 break;  
  172.   
  173.             }  
  174.   
  175.         }  
  176.   
  177.     }  
  178.   
  179.     close(sockfd);  
  180.   
  181.     return 0;  
  182.   
  183. }  

服务器端运行结果

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. $ ./tcp_p_p_chat_server 172.18.229.62 7576 5  
  2. wait for connect  
  3. server: got connection from 172.18.229.62, port 60199, socket 4  
  4. input the message to send:hello  
  5. input the message to send:message recv successful :'hi',2Byte recv  
  6.   
  7. input the message to send:  
  8. input the message to send:quit  
  9. i will close the connect!<span style="color:#339999;">  
  10. </span>  

客户端运行结果

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. $ ./tcp_p_p_chat_client 172.18.229.62 7576   
  2. socket created  
  3. server connected  
  4. pls send message to send:recv successful:'hello',5 byte recv  
  5. hi  
  6. pls send message to send:quit  
  7.  i will quit!<span style="color:#339999;">  
  8. </span>  

原文链接

http://blog.csdn.net/geng823/article/details/41748819

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值