服务器端的代码如下所示。
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7
8 #define N 128
9 #define errlog(errmsg) do{perror(errmsg);\
10 printf("---%s---%s---%d---\n",\
11 __FILE__, __func__, __LINE__);\
12 return -1;\
13 }while(0)
14 int main(int argc, const char *argv[])
15 {
16 int sockfd, acceptfd;
17
18 struct sockaddr_in serveraddr, clientaddr;
19 socklen_t addrlen = sizeof(serveraddr);
20 char buf[N] = "";
21
22 bzero(&serveraddr, addrlen);
23 bzero(&clientaddr, addrlen);
24
25 /*提示程序需要命令行传参*/
26 if(argc < 3){
27 fprintf(stderr, "Usage: %s ip port\n", argv[0]);
28 return -1;
29 }
30
31 /*创建套接字*/
32 if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
33 errlog("socket error");
34 }
35
36 /*填充网络信息结构体
37 *inet_addr:将点分十进制地址转换为网络字节序的整型数据
38 *htons:将主机字节序转换为网络字节序
39 *atoi:将数字型字符串转化为整型数据
40 */
41 serveraddr.sin_family = AF_INET;
42 serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
43 serveraddr.sin_port = htons(atoi(argv[2]));
44
45 /*将套接字与服务器网络信息结构体把绑定*/
46 if(bind(sockfd, (struct sockaddr *)&serveraddr, addrlen) < 0){
47 errlog("bind error");
48 }
49
50 /*将套接字设置为被动监听模式*/
51 if(listen(sockfd, 5) < 0){
52 errlog("listen error");
53 }
54
55 /*阻塞等待客户端的连接请求*/
56 /*可以将后两个参数设置为NULL,表示不关注客户端的信息,不影响通信*/
57 if((acceptfd = accept(sockfd,\
58 (struct sockaddr *)&clientaddr, &addrlen)) < 0){
59 errlog("accept error");
60 }
61
62 printf("ip: %s, port: %d\n",\
63 inet_ntoa(clientaddr.sin_addr),\
64 ntohs(clientaddr.sin_port));
65
66 ssize_t bytes;
67
68 while(1){
69 if((bytes = recv(acceptfd, buf, N, 0)) < 0){
70 errlog("recv error");
71 }
72 else if(bytes == 0){
73 errlog("no data");
74 }
75 else{
76 if(strncmp(buf, "quit", 4) == 0){
77 printf("client quit\n");
78 goto err;
79 }
80 else{
81 printf("client: %s\n", buf);
82 strcat(buf, "-server");
83
84 if(send(acceptfd, buf, N, 0) < 0){
85 errlog("send error");
86 }
87 }
88 }
89 }
90
91 return 0;
92 err:
93 close(acceptfd);
94 close(sockfd);
95 return 0;
96 }
客户端代码如下所示。
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7
8 #define N 128
9 #define errlog(errmsg) do{perror(errmsg);\
10 printf("---%s---%s---%d---\n",\
11 __FILE__, __func__, __LINE__);\
12 return -1;\
13 }while(0)
14 int main(int argc, const char *argv[])
15 {
16 int sockfd;
17 struct sockaddr_in serveraddr;
18 socklen_t addrlen = sizeof(serveraddr);
19 char buf[N] = "";
20
21 /*提示程序需要命令行传参*/
22 if(argc < 3){
23 fprintf(stderr, "Usage: %s ip port\n", argv[0]);
24 return -1;
25 }
26
27 /*创建套接字*/
28 if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
29 errlog("socket error");
30 }
31
32 /*填充网络信息结构体
33 *inet_addr:将电分十进制地址转换为网络字节序的整型数据
34 *htons:将主机字节序转换为网络字节序
35 *atoi:将数字型字符串转化为整型数据
36 */
37 serveraddr.sin_family = AF_INET;
38 serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
39 serveraddr.sin_port = htons(atoi(argv[2]));
40
41 #if 0
42 系统可以随机为客户端指定IP地址和端口号,客户端也可以自己指定
43 struct sockaddr_in clientaddr;
44 clientaddr.sin_family = AF_INET;
45 clientaddr.sin_addr.s_addr = inet_addr(argv[3]);
46 clientaddr.sin_port = htons(atoi(argv[4]));
47
48 if(bind(sockfd, (struct sockaddr *)&clientaddr, addrlen) < 0){
49 errlog("bind error");
50 }
51 #endif
52
53 /*发送客户端连接请求*/
54 if(connect(sockfd, (struct sockaddr *)&serveraddr, addrlen) < 0){
55 errlog("connect error");
56 }
57
58 while(1){
59 fgets(buf, N, stdin);
60 buf[strlen(buf) - 1] = '\0';
61
62 if(send(sockfd, buf, N, 0) < 0){
63 errlog("send error");
64 }
65 else{
66 if(strncmp(buf,"quit", 4) == 0){
67 goto err;
68 }
69
70 if(recv(sockfd, buf, N, 0) < 0){
71 errlog("recv error");
72 }
73
74 printf("server: %s\n", buf);
75 }
76 }
77
78 return 0;
79 err:
80 close(sockfd);
81 return 0;
82 }
服务器运行结果如下所示。
linux@Master:~/1000phone/net/tcp$ ./server 192.168.44.134 7777
ip: 192.168.44.134, port: 45425
client: hello world
client quit
客户端运行结果如下所示,运行客户端发起连接请求。连接成功后,发送字符串。之后接收服务器端的发送的字符串。当输入“quit”时,进程断开连接,并退出。
linux@Master:~/1000phone/net/tcp$ ./client 192.168.44.134 7777
hello world
server: hello world-server
quit