• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 HiHope Open Source Organization .
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http:// www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  *
14  * limitations under the License.
15  */
16 
17 #include <errno.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <unistd.h>
21 
22 #include "net_common.h"
23 
24 static char request[128] = "";
TcpServerTest(unsigned short port)25 void TcpServerTest(unsigned short port)
26 {
27     ssize_t retval = 0;
28     int backlog = 1;
29     int sockfd = socket(AF_INET, SOCK_STREAM, 0); // TCP socket
30     int connfd = -1;
31 
32     struct sockaddr_in clientAddr = {0};
33     socklen_t clientAddrLen = sizeof(clientAddr);
34     struct sockaddr_in serverAddr = {0};
35     serverAddr.sin_family = AF_INET;
36     serverAddr.sin_port = htons(port);  // 端口号,从主机字节序转为网络字节序
37     serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); // 允许任意主机接入, 0.0.0.0
38 
39     retval = bind(sockfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)); // 绑定端口
40     if (retval < 0) {
41         printf("bind failed, %ld!\r\n", retval);
42         close(sockfd);
43     }
44     printf("bind to port %u success!\r\n", port);
45 
46     retval = listen(sockfd, backlog); // 开始监听
47     if (retval < 0) {
48         printf("listen failed!\r\n");
49         printf("do_cleanup...\r\n");
50         close(sockfd);
51     }
52     printf("listen with %d backlog success!\r\n", backlog);
53 
54     // 接受客户端连接,成功会返回一个表示连接的 socket , clientAddr 参数将会携带客户端主机和端口信息 ;失败返回 -1
55     // 此后的 收、发 都在 表示连接的 socket 上进行;之后 sockfd 依然可以继续接受其他客户端的连接,
56     //  UNIX系统上经典的并发模型是“每个连接一个进程”——创建子进程处理连接,父进程继续接受其他客户端的连接
57     //  鸿蒙liteos-a内核之上,可以使用UNIX的“每个连接一个进程”的并发模型
58     //     liteos-m内核之上,可以使用“每个连接一个线程”的并发模型
59     connfd = accept(sockfd, (struct sockaddr *)&clientAddr, &clientAddrLen);
60     if (connfd < 0) {
61         printf("accept failed, %d, %d\r\n", connfd, errno);
62         printf("do_cleanup...\r\n");
63         close(sockfd);
64     }
65     printf("accept success, connfd = %d!\r\n", connfd);
66     printf("client addr info: host = %s, port = %d\r\n", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port));
67 
68     // 后续 收、发 都在 表示连接的 socket 上进行;
69     retval = recv(connfd, request, sizeof(request), 0);
70     if (retval < 0) {
71         printf("recv request failed, %ld!\r\n", retval);
72         printf("do_cleanup...\r\n");
73         close(sockfd);
74     }
75     printf("recv request{%s} from client done!\r\n", request);
76 
77     retval = send(connfd, request, strlen(request), 0);
78     if (retval <= 0) {
79         printf("send response failed, %ld!\r\n", retval);
80         printf("do_cleanup...\r\n");
81         close(sockfd);
82     }
83     printf("send response{%s} to client done!\r\n", request);
84 
85 do_disconnect:
86     sleep(1);
87     close(connfd);
88     sleep(1); // for debug
89 SERVER_TEST_DEMO(TcpServerTest);