由于公司需要开发底层套接字通信,所以把大一的C重新拾回来学习,但是就学校的那点皮毛远远达不到公司项目的要求,一切重来,学习Linux下的C编程。
以Linux下TCP socket通信为实例。
在Socket通信中,服务器端分为socket初始化、绑定、监听、接受连接、发送接收数据五个过程,客户端分为socket初始化、连接服务器socket、发送接收数据三个过程。如图所示。
作为初学者,socket套接字学习的关键点在于那几个函数的学习和理解。
代码先上,解析在注释中:
说明:本代码已经加入多线程问题,请查阅时注意。Linux下GCC编译通过。
server.c:
1 /*
2 * server.c
3 *
4 * Created on: 2011-3-13
5 * Author: n2
6 */
7
8 #include <pthread.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include <sys/types.h>
14 #include <sys/socket.h>
15 #include <netinet/in.h>
16
17 #define PORTL 8742
18
19 pthread_t th1,th2;
20 //声明读写函数
21 void *recv_info(int newsockfd);
22 void *send_info(int newsockfd);
23 //输出错误提示
24 void error(const char *msg)
25 {
26 perror(msg);
27 exit(1);
28 }
29
30 int main(int argc, char *argv[])
31 {
32 int sockfd, newsockfd;
33 unsigned int clilen;
34 struct sockaddr_in serv_addr, cli_addr;//socket通信中Internet地址变量定义
35
36 sockfd = socket(AF_INET, SOCK_STREAM, 0);//初始化socket
37 if (sockfd < 0)
38 error("ERROR opening socket");
39 bzero((char *) &serv_addr, sizeof(serv_addr));//地址变量进行清零
40
41 serv_addr.sin_family = AF_INET;
42 serv_addr.sin_addr.s_addr = INADDR_ANY;
43 serv_addr.sin_port = htons(PORTL);//地址变量添加协议簇、监听地址、端口
44 if (bind(sockfd, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)//绑定socket
45 error("ERROR on binding");
46 listen(sockfd,10);
47
48 clilen = sizeof(cli_addr);
49
50 while(1){
51 newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr,&clilen);//阻塞等待连接
52
53 //连接成功,创建读写线程
54 memset(&th1, 0, sizeof(th1));
55 memset(&th2, 0, sizeof(th2));
56 int thr1 = pthread_create(&th1,NULL,recv_info,newsockfd);
57 if(thr1!=0)
58 printf("recv Creation failed!/n");
59 int thr2 = pthread_create(&th2,NULL,send_info,newsockfd);
60 if(thr2!=0)
61 printf("send Creation failed!/n");
62 }
63 //等待线程结束
64 pthread_join(th1,NULL);
65 pthread_join(th2,NULL);
66
67 close(sockfd);
68 return 0;
69 }
70
71 //读取来自于客户端的数据并显示
72 void *recv_info(int newsockfd)
73 {
74 int n;
75 char buffer[512];
76
77 if (newsockfd < 0)
78 pthread_exit((void *)1);
79 else
80 {
81 while(1)
82 {
83 bzero(buffer,512);
84 n = recv(newsockfd,buffer,sizeof(buffer),0);
85 printf("From client: %s/n",buffer);
86 if (n < 0)
87 pthread_exit(NULL);
88 else
89 //当读取数据为'0'时关闭读取线程
90 if(buffer[0]=='0')
91 pthread_exit(NULL);
92 }
93 }
94 }
95 //向客户端发送数据
96 void *send_info(int newsockfd)
97 {
98 int n;
99 char buffer[256];
100 bzero(buffer,256);
101 while(1)
102 {
103 if(newsockfd<0)
104 error("ERROR on accept");
105 gets(buffer);
106 n =send(newsockfd,buffer,sizeof(buffer),0);
107 if (n < 0)
108 error("ERROR writing to socket");
109 if(buffer[0]=='0')
110 //当发送数据为'0'时关闭发送线程
111 pthread_exit((NULL);
112 }
113 }
client.c
1 /*
2 * client.c
3 *
4 * Created on: 2011-3-13
5 * Author: n2
6 */
7
8 #include <pthread.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <errno.h>
12 #include <string.h>
13 #include <netdb.h>
14 #include <sys/types.h>
15 #include <netinet/in.h>
16 #include <sys/socket.h>
17 #include <unistd.h>
18
19 #define PORTL 8742
20 pthread_t th1,th2;
21
22 void *send_info(int saiCId);
23 void *read_info(int saiCId);
24
25 int main()
26 {
27 struct sockaddr_in saiClient;
28 int saiCId , connectId ;
29
30 char * host_name="192.168.1.233";//服务器端IP地址
31 struct hostent *server_host_name;
32 server_host_name = gethostbyname(host_name);
33
34
35 saiClient.sin_family = AF_INET;
36 saiClient.sin_port = htons(PORTL);
37 saiClient.sin_addr.s_addr= ((struct in_addr *)(server_host_name->h_addr))->s_addr;//转义字符串格式的IP地址
38
39 saiCId = socket(AF_INET,SOCK_STREAM,0);
40
41 memset(&th1, 0, sizeof(th1));
42 memset(&th2, 0, sizeof(th2));
43
44
45 connectId = connect(saiCId,(struct sockaddr *)(&saiClient),sizeof(struct sockaddr_in));
46 if(connectId<0)
47 printf("connect failed!");
48
49 int thr1 = pthread_create(&th1,NULL,send_info,saiCId);
50 if(thr1!=0)
51 printf(" Send Thread Creation failed!/n");
52
53 int thr2 = pthread_create(&th2,NULL,read_info,saiCId);
54 if(thr2!=0)
55 printf(" Send Thread Creation failed!/n");
56
57 pthread_join(th1,NULL);
58 pthread_join(th2,NULL);
59
60 close(saiCId);
61 }
62
63 void *send_info(int saiCId)
64 {
65 int n;
66 char buffer[256];
67 while (1)
68 {
69 bzero(buffer, 256);
70 gets(buffer);
71
72 n = send(saiCId, buffer, sizeof(buffer), 0);
73 if (n < 0)
74 error("ERROR writing to socket");
75 if (buffer[0] == '0')
76 return NULL;
77 }
78 }
79
80 void *read_info(int saiCId)
81 {
82 int n;
83 char buffer[512];
84
85 if (saiCId < 0)
86 pthread_exit((void *)1);
87 while(1)
88 {
89 bzero(buffer,512);
90 n = recv(saiCId,buffer,sizeof(buffer),0);
91 printf("From server: %s/n", buffer);
92 if (n < 0)
93 pthread_exit((void *)1);
94 else
95 if(buffer[0]=='0')
96 return NULL;
97 }
98
99 }