Linux网络编程 - TCP Socket 简单练习:新进程辅助通信

补充:

在进行地址转换时用inet_pton

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. //将ip地址转换为32位网络地址 inet_addr inet_aton或者inet_pton    
  2. //但为了安全,最好用inet_pton代替inet_addr和inet_aton这两个函数  
  3. //三种方式使用方法如下,其中argv[1]为从命令行获得的IP地址  
  4. 1. inet_aton(argv[1], (struct in_addr *) &dest.sin_addr.s_addr);  
  5. 2. server_addr.sin_addr.s_addr = inet_addr(argv[1]);  
  6. 3. inet_pton(AF_INET, argv[1], &server_addr.sin_addr);//最安全  

运行方式

服务器端,可以直接运行命令,也可以带参数运行,如果不带参数运行,则程序自主获取主机ip,然后默认设定port和lisnum的值。其中port默认为6666,lisnum默认为5.
[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. ./socket_select_server IP地址(可选) 端口号(可选)监听队列大小(可选)    

客户端,必须指定服务器的IP地址和端口号,例如:

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. ./socket_select_client 172.18.229.60 6666    

服务器端代码

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. /************************************************************************* 
  2.     > File Name: tcp_server.c 
  3.     > Author: genglut 
  4.     > Mail: genglut@163.com 
  5.     > Created Time: 2014年12月22日 星期一 10时14分53秒 
  6.  ************************************************************************/  
  7.   
  8. /* 
  9. struct sockaddr_in  
  10. {   
  11.       short int sin_family;                // 地址协议   
  12.       in_port_t sin_port;                  // 端口号   
  13.       struct in_addr sin_addr;           // IP地址  
  14.       unsigned char sin_zero[8];        // 预留位  
  15. };   
  16.  
  17. struct in_addr  
  18. {   
  19.       _u32 s_addr;             // 32位地址   
  20. }; 
  21. */  
  22.   
  23.   
  24. #include <stdio.h>  
  25. #include <stdlib.h>  
  26. #include <errno.h>  
  27. #include <string.h>  
  28. #include <sys/types.h>  
  29. #include <netinet/in.h>  
  30. #include <sys/socket.h>  
  31. #include <sys/wait.h>  
  32. #include <unistd.h>  
  33. #include <arpa/inet.h>  
  34. #include <net/if.h>  
  35. #include <sys/ioctl.h>  
  36.   
  37. #define MAXBUF 1024  
  38.   
  39. void get_ip(char * str, char *ip);//获取本地IP地址  
  40.   
  41. int main(int argc, char *argv[])  
  42. {  
  43.       
  44.     //用于测试命令行输入的值的情况  
  45.     //printf("argv[0] = %s\n", argv[0]);      
  46.     //printf("argv[1] = %s\n", argv[1]);      
  47.     //printf("argv[2] = %s\n", argv[2]);      
  48.     //printf("argv[3] = %s\n", argv[3]);      
  49.   
  50.     pid_t pid;  
  51.     int sockfd, newfd;  
  52.     socklen_t len;  
  53.     struct sockaddr_in server_addr, client_addr;//结构体sockaddr_in  
  54.     unsigned int server_port, lisnum;//用int也可以  
  55.     char buf[MAXBUF + 1];  
  56.       
  57.     if(argv[1] && argv[2])//要根据argv[1]的情况来判断argv[2]的情况,否则会出错  
  58.         server_port = atoi(argv[2]);  
  59.     else  
  60.         server_port = 6666;  
  61.           
  62.     if(argv[1] && argv[2] && argv[3])//与上面道理相同  
  63.         lisnum = atoi(argv[3]);  
  64.     else  
  65.         lisnum = 5;   
  66.   
  67.     bzero(&server_addr, sizeof(server_addr));//也可以用memset  
  68.     server_addr.sin_family = AF_INET;  
  69.     server_addr.sin_port = htons(server_port);//转换为网络字节序  
  70.       
  71.     if(argv[1])  
  72.         server_addr.sin_addr.s_addr = inet_addr(argv[1]);  
  73.     else  
  74.     {  
  75.         char ip[128];  
  76.         get_ip("eno16777736", ip);  
  77.         server_addr.sin_addr.s_addr = inet_addr(ip);  
  78.     }  
  79.   
  80.     //建立sockfd  
  81.     if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)  
  82.     {  
  83.         perror("socket");  
  84.         exit(EXIT_FAILURE);  
  85.     }  
  86.       
  87.     //输出ip和port信息,用于测试  
  88.     printf("server_ip = %s\nserver_port = %d\nlisnum = %d\n", inet_ntoa(server_addr.sin_addr), server_port, lisnum);  
  89.   
  90.     //绑定sockfd和服务器的IP地址server_addr  
  91.     if(bind(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)  
  92.     {  
  93.         perror("bind");  
  94.         exit(EXIT_FAILURE);  
  95.     }  
  96.       
  97.     //监听sockfd  
  98.     if(listen(sockfd, lisnum) == -1)  
  99.     {  
  100.         perror("listen");  
  101.         exit(EXIT_FAILURE);  
  102.     }  
  103.   
  104.     printf("wait client connect ...\n");  
  105.   
  106.     //等待接收客户端的连接  
  107.     //连接成功后,客户端地址信息存储在client_addr中  
  108.     //新建立的socket描述符存储在newfd中  
  109.     len = sizeof(struct sockaddr);  
  110.     if((newfd = accept(sockfd, (struct sockaddr *)&client_addr, &len)) == -1)  
  111.     {  
  112.         perror("accept");  
  113.         exit(EXIT_FAILURE);  
  114.     }  
  115.   
  116.     //创建子进程  
  117.     if((pid = fork()) == -1)  
  118.     {  
  119.         perror("fork");  
  120.         exit(EXIT_FAILURE);  
  121.     }  
  122.     else if(pid == 0) //子进程用于向客户端发送消息  
  123.     {  
  124.         close(sockfd);  
  125.         while(1)  
  126.         {  
  127.             bzero(buf, sizeof(buf));//清空buf  
  128.             printf("pls input the message to send:  ");  
  129.             fgets(buf, sizeof(buf)-1, stdin);//从终端接收输入  
  130.   
  131.             if(!strncasecmp(buf, "quit", 4))//判断是否为退出  
  132.             {  
  133.                 printf("i will close the connect!\n");  
  134.                 break;  
  135.             }  
  136.   
  137.             if(send(newfd, buf, strlen(buf)-1, 0) < 0 )//向客户端发送消息  
  138.             {  
  139.                 printf("message '%s' send failure !\n", buf);  
  140.                 printf("errno code is %d, errno message is '%s'\n", errno, strerror(errno));  
  141.                 break;  
  142.             }  
  143.         }  
  144.         close(newfd);  
  145.   
  146.     }  
  147.     else //父进程用于从客户端接收消息  
  148.     {  
  149.         close(newfd);  
  150.         while(1)  
  151.         {  
  152.             bzero(buf, sizeof(buf));  
  153.             len = recv(newfd, buf, sizeof(buf)-1, 0);//从客户端接收消息  
  154.             if(len > 0 )  
  155.                 printf("message recv successful : '%s', %d Byte recv\n", buf, len);  
  156.             else if(len < 0)  
  157.             {  
  158.                 printf("recv failure !\nerrno code is %d, errno message is '%s'\n", errno, strerror(errno));  
  159.                 break;  
  160.             }  
  161.             else//如果客户端已关闭  
  162.             {  
  163.                 printf("the other one close quit\n");  
  164.                 break;  
  165.             }  
  166.         }  
  167.     }  
  168.   
  169.     close(sockfd);  
  170.   
  171.     return 0;  
  172. }  
  173.   
  174.   
  175. void get_ip(char * str, char *ip)  
  176. {  
  177.     int inet_sock;  
  178.     struct ifreq ifr;  
  179.     inet_sock = socket(AF_INET, SOCK_DGRAM, 0);  
  180.     strcpy(ifr.ifr_name, str);//#include <net/if.h>  
  181.     if (ioctl(inet_sock, SIOCGIFADDR, &ifr) < 0)//#include <sys/ioctl.h>  
  182.     {  
  183.         perror("ioctl");  
  184.         exit(EXIT_FAILURE);  
  185.     }  
  186.     sprintf(ip,"%s", inet_ntoa(((struct sockaddr_in*)&(ifr.ifr_addr))->sin_addr));  
  187.     close(inet_sock);     
  188. }  

客户端代码

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. /************************************************************************* 
  2.     > File Name: tcp_client.c 
  3.     > Author: genglut 
  4.     > Mail: genglut@163.com 
  5.     > Created Time: 2014年12月22日 星期一 11时31分38秒 
  6.  ************************************************************************/  
  7.   
  8. #include <stdio.h>  
  9. #include <string.h>  
  10. #include <errno.h>  
  11. #include <sys/socket.h>  
  12. #include <resolv.h>  
  13. #include <stdlib.h>  
  14. #include <netinet/in.h>  
  15. #include <arpa/inet.h>  
  16. #include <unistd.h>  
  17.   
  18. #define MAXBUF 1024  
  19.   
  20. int main(int argc, char *argv[])  
  21. {  
  22.     pid_t pid;  
  23.     int sockfd;  
  24.     socklen_t len;  
  25.     struct sockaddr_in server_addr;  
  26.     char buf[MAXBUF + 1];  
  27.   
  28.     if(argc != 3)  
  29.     {  
  30.         printf("error failure, it must be:\n\t\t%s IP port \n", argv[0]);  
  31.         exit(EXIT_FAILURE);  
  32.     }  
  33.   
  34.     if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)  
  35.     {  
  36.         perror("socket");  
  37.         exit(EXIT_FAILURE);  
  38.     }  
  39.   
  40.     bzero(&server_addr, sizeof(server_addr));  
  41.     server_addr.sin_family = AF_INET;  
  42.     server_addr.sin_port = htons(atoi(argv[2]));  
  43.     server_addr.sin_addr.s_addr = inet_addr(argv[1]);  
  44.   
  45.     if(connect(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)  
  46.     {  
  47.         perror("connect");  
  48.         exit(EXIT_FAILURE);  
  49.     }  
  50.   
  51.     printf("already connected to server %s\n", argv[1]);  
  52.   
  53.     if((pid = fork()) == -1)  
  54.     {  
  55.         perror("fork");  
  56.         exit(EXIT_FAILURE);  
  57.     }  
  58.     else if(pid == 0)  
  59.     {  
  60.         while(1)  
  61.         {  
  62.             bzero(buf, sizeof(buf));  
  63.             len = recv(sockfd, buf, sizeof(buf)-1, 0);  
  64.             if(len >0)  
  65.                 printf("recv successful:'%s', %d byte recv\n", buf, len);  
  66.             else   
  67.             {  
  68.                 printf("the server close, quit\n");  
  69.                 break;  
  70.             }  
  71.         }  
  72.     }  
  73.     else   
  74.     {  
  75.         while(1)  
  76.         {  
  77.             bzero(buf, sizeof(buf));  
  78.             printf("pls input message to send: ");  
  79.             fgets(buf, sizeof(buf)-1, stdin);  
  80.             if(!strncasecmp(buf, "quit", 4))  
  81.             {  
  82.                 printf("i will quit!\n");  
  83.                 break;  
  84.             }  
  85.             len = send(sockfd, buf, strlen(buf)-1, 0);  
  86.             if(len < 0)  
  87.             {  
  88.                 perror("send");  
  89.                 break;  
  90.             }  
  91.         }  
  92.     }  
  93.   
  94.     close(sockfd);  
  95.     printf("i quited!\n");  
  96.     return 0;  
  97. }  

原文链接

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值