Linux下的TCP连接

TCP连接可以分为三个情况,第一种是单进程,一个服务端只能有一个客户端;第二种是多进程,一个服务端可以接受多个客户端;第三种是多线程,相对于多进程而言更稳定,因为线程相对于进程是各自私有资源,各自独立。

  • 第一种—–单进程

tcp_client 客户端

  1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<sys/socket.h>
  4 #include<netinet/in.h>
  5 #include<arpa/inet.h>
  6 #include<fcntl.h>
  7 #include<string.h>
  8 #include<stdlib.h>
  9 #include<pthread.h>
 10 
 11 static void usage(const char* proc)
 12 {
 13     printf("Usage:%s [local_ip] [local_port]\n",proc);
 14 }
 15 
 16 int main(int argc,char* argv[])
 17 {
 18     if(argc!=3)
 19     {
 20         usage(argv[0]);
 21         return 1;
 22     }
 23 
 24     int sock=socket(AF_INET,SOCK_STREAM,0);
 25     if(sock<0)
 26     {
 27         perror("socket");
 28         return(2);
 29     }
 30 
 31     struct sockaddr_in peer;
 32     peer.sin_family=AF_INET;
 33     peer.sin_port=htons(atoi(argv[2]));
 34     peer.sin_addr.s_addr=inet_addr(argv[1]);
 35 
 36     if(connect(sock,(struct sockaddr*)&peer,sizeof(peer))<0)
 37     {
 38         perror("connect");
 39         return 3;
 40     }
 41     char buf[1024];
 42     while(1)
 43     {
 44         printf("Please Enter# ");
 45         fflush(stdout);
 46         ssize_t s=read(0,buf,sizeof(buf)-1);
 47         if(s>0)
 48         {
 49             buf[s-1]=0;
 50             write(sock,buf,strlen(buf));
 51             ssize_t _s=read(sock,buf,sizeof(buf)-1);
 52             if(_s>0)
 53             {
 54                 buf[_s]=0;
 55                 printf("server echo# %s\n",buf);
 56             }
 57             else if(s==0)
 58             {
 59                 printf("server quit!\n");
 60                 break;
 61             }else{
 62                 break;
 63             }
 64         }
 65     }
 66     close(sock);
 67     return 0;
 68 }

tcp_server 服务端

  1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<sys/socket.h>
  4 #include<netinet/in.h>
  5 #include<arpa/inet.h>
  6 #include<fcntl.h>
  7 #include<string.h>
  8 #include<stdlib.h>
  9 #include<pthread.h>
 10 
 11 static void usage(const char* proc)
 12 {
 13     printf("Usage:%s [local_ip] [local_port]\n",proc);
 14 }
 15 
 16 int startup(const char* _ip,int _port)
 17 {
 18     int sock=socket(AF_INET,SOCK_STREAM,0);
 19     if(sock<0)
 20     {
 21         perror("socket");
 22         exit(2);
 23     }
  24     printf("fd:%d\n",sock);
 25     struct sockaddr_in local;
 26     local.sin_family=AF_INET;
 27     local.sin_port=htons(_port);
 28     local.sin_addr.s_addr=inet_addr(_ip);
 29     if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0)
 30     {
 31         perror("bind");
 32         exit(3);
 33     }
 34     if(listen(sock,10)<0)
 35     {
 36         perror("listen");
 37         exit(4);
 38     }
 39     return sock;
 40 }
 41 
 42 int main(int argc,char *argv[])
 43 {
 44     if(argc!=3)
 45     {
 46         usage(argv[0]);
 47         return 1;
 48     }
 49     int listen_sock=startup(argv[1],atoi(argv[2]));
 50     while(1)
 51     {
 52         struct sockaddr_in client;
 53         socklen_t len=sizeof(client);
 54         int new_sock=accept(listen_sock,(struct sockaddr*)&client,&len);
 55         if(new_sock<0)
 56         {
 57             perror("accept");
 58             continue;
 59         }
 60 
 61         printf("get a new client:[%s:%d]\n",inet_ntoa(client.sin_addr),\
 62                 ntohs(client.sin_port));
 63 
 98    char buf[1024];
 99    while(1)
100    {
101         ssize_t s=read(new_sock,buf,sizeof(buf)-1);
102         if(s>0)
103         {
104              buf[s]=0;
105              printf("client# %s\n",buf);
106              write(new_sock,buf,strlen(buf));
107         }else if(s==0){
108              printf("client quit!\n");
109              break;
110         }else{
111              perror("read");
112              break;
113              char buf[1024];
114              while(1)
115              {
116                   ssize_t s=read(new_sock,buf,sizeof(buf)-1);
117                   if(s>0)
118                   {
119                      buf[s]=0;
120                      printf("client# %s\n",buf);
121                      write(new_sock,buf,strlen(buf));
122                   }else if(s==0){
123                      printf("client quit!\n");
124                      break;
125                   }else{
126                      perror("read");
127                      break;
128                  }
129            }
130      close(new_sock);
131     }
132 }

单进程TCP连接可以直接使用一个主机上的两个终端来测试。
即在一个终端运行tcp_server,一个终端运行tcp_client直接对话。

  • 第二种—-多进程
    多进程tcp只用修改tcp_server.c代码,在代码中创建子进程即可。
  1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<sys/socket.h>
  4 #include<netinet/in.h>
  5 #include<arpa/inet.h>
  6 #include<fcntl.h>
  7 #include<string.h>
  8 #include<stdlib.h>
  9 #include<pthread.h>
 10 
 11 static void usage(const char* proc)
 12 {
 13     printf("Usage:%s [local_ip] [local_port]\n",proc);
 14 }
 15 
 16 int startup(const char* _ip,int _port)
 17 {
 18     int sock=socket(AF_INET,SOCK_STREAM,0);
 19     if(sock<0)
 20     {
 21         perror("socket");
 22         exit(2);
 23     }
 24     printf("fd:%d\n",sock);
 25     struct sockaddr_in local;
 26     local.sin_family=AF_INET;
 27     local.sin_port=htons(_port);
 28     local.sin_addr.s_addr=inet_addr(_ip);
 29     if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0)
 30     {
 31         perror("bind");
 32         exit(3);
 33     }
 34     if(listen(sock,10)<0)
 35     {
 36         perror("listen");
 37         exit(4);
 38     }
 39     return sock;
 40 }
 41 
 42 int main(int argc,char *argv[])
 43 {
 44     if(argc!=3)
 45     {
 46         usage(argv[0]);
 47         return 1;
 48     }
 49     int listen_sock=startup(argv[1],atoi(argv[2]));
 50     while(1)
 51     {
 52         struct sockaddr_in client;
 53         socklen_t len=sizeof(client);
 54         int new_sock=accept(listen_sock,(struct sockaddr*)&client,&len);
 55         if(new_sock<0)
 56         {
 57             perror("accept");
 58             continue;
 59         }
 60 
 61         printf("get a new client:[%s:%d]\n",inet_ntoa(client.sin_addr),\
 62                 ntohs(client.sin_port));
 63 
 64         pid_t id=fork();
 65         if(id<0)
 66         {
 67             perror("fork");
 68             continue;
 69         }else if(id==0)
 70         {
 71             if(fork()>0){
 72                 exit(0);
 73             }
 74             char buf[1024];
 75             while(1)
 76             {
 77                 ssize_t s=read(new_sock,buf,sizeof(buf)-1);
 78                 if(s>0)
 79                 {
 80                     buf[s]=0;
 81                     printf("client# %s\n",buf);
 82                     write(new_sock,buf,strlen(buf));
 83                 }else if(s==0){
 84                     printf("client quit!\n");
 85                     break;
 86                 }else{
 87                     perror("read");
 88                     break;
 89                 }
 90             }
 91             close(new_sock);
 92             exit(0);
 93         }else{
 94             close(new_sock);
 95             waitpid(id,NULL,0);
 96         }
131     }
132 }

多进程tcp测试可以通过两个主机连接一个局域网完成。

  • 切换到root用户,关闭自己和对方主机的防火墙—-service iptables stop
  • 检查是否有sshd—-ps aux | grep ssh
  • 使用命令查看IP地址是否在一个局域网内—-ifconfig
  • 与对方主机ping一下看能不能通—-ping 192.xxx.xxx.xxx
  • 将tcp_client执行文件发送到对方主机—-scp tcp_client 192.xxx.xxx.xxx:/home
  • 运行tcp_server,对方主机在/home目录下运行tcp_client
    这里写图片描述
    这里写图片描述
    这里写图片描述

  • 第三种—-多线程
    多线程是将tcp_server.c的代码改为线程形式。

  1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<sys/socket.h>
  4 #include<netinet/in.h>
  5 #include<arpa/inet.h>
  6 #include<fcntl.h>
  7 #include<string.h>
  8 #include<stdlib.h>
  9 #include<pthread.h>
 10 
 11 static void usage(const char* proc)
 12 {
 13     printf("Usage:%s [local_ip] [local_port]\n",proc);
 14 }
 15 
 16 int startup(const char* _ip,int _port)
 17 {
 18     int sock=socket(AF_INET,SOCK_STREAM,0);
 19     if(sock<0)
 20     {
 21         perror("socket");
 22         exit(2);
 23     }
 24     printf("fd:%d\n",sock);
 25     struct sockaddr_in local;
 26     local.sin_family=AF_INET;
 27     local.sin_port=htons(_port);
 28     local.sin_addr.s_addr=inet_addr(_ip);
 29     if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0)
 30     {
 31         perror("bind");
 32         exit(3);
 33     }
 34     if(listen(sock,10)<0)
 35     {
 36         perror("listen");
 37         exit(4);
 38     }
 39     return sock;
 40 }
 41 
 42 void *request(void *arg)
 43 {
 44     int new_sock=(int)arg;
 45     char buf[1024];
 46     while(1)
 47     {
 48         ssize_t s=read(new_sock,buf,sizeof(buf)-1);
 49         if(s>0){
 50             buf[s]=0;
 51             printf("client# %s\n",buf);
 52             write(new_sock,buf,strlen(buf));
 53         }else if(s==0){
 54             printf("client quit!\n");
 55             break;
 56         }else{
 57             perror("read");
 58             break;
 59         }
 60     }
 61     close(new_sock);
 62     return  (void*)0;
 63 }
 64 
 65 int main(int argc,char *argv[])
 66 {
 67     if(argc!=3)
 68     {
 69         usage(argv[0]);
 70         return 1;
 71     }
 72     int listen_sock=startup(argv[1],atoi(argv[2]));
 73     while(1)
 74     {
 75         struct sockaddr_in client;
 76         socklen_t len=sizeof(client);
 77         int new_sock=accept(listen_sock,(struct sockaddr*)&client,&len);
 78         if(new_sock<0)
 79         {
 80             perror("accept");
 81             continue;
 82         }
 83 
 84         printf("get a new client:[%s:%d]\n",inet_ntoa(client.sin_addr),\
 85                 ntohs(client.sin_port));
 86 
 87     pthread_t id;
 88     pthread_create(&id,NULL,request,(void*)new_sock);
 89     pthread_detach(id);
 90 
158     }
159 }

这里写图片描述
这里写图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值