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 }