-
Notifications
You must be signed in to change notification settings - Fork 0
/
tcp_server.cpp
137 lines (117 loc) · 3.15 KB
/
tcp_server.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include "iostream"
#include "netdb.h"
#include "stdio.h"
#include "stdlib.h"
#include "sys/socket.h"
#include "unistd.h"
#include "arpa/inet.h"
#include "string.h"
#include "memory.h"
#include "signal.h"
#include "time.h"
int sockfd;
void sig_handler(int signo)
{
if (signo == SIGINT)
{
printf("Server close \n");
close(sockfd);
exit(1);
}
}
//输出连接上来的客户端相关信息
void out_addr(struct sockaddr_in *clientaddr)
{
//将端口从网络字节序转成主机字节序
int port = ntohs(clientaddr->sin_port);
char ip[16];
memset(ip, 0, sizeof(ip));
inet_ntop(AF_INET,
&clientaddr->sin_addr.s_addr, ip, sizeof(ip));
printf("client:%s(%d)connected\n", ip, port);
}
void do_service(int fd)
{
//获取系统时间
long t = time(0);
char *s = ctime(&t);
size_t size = strlen(s) * sizeof(char);
//将服务器端的系统时间写到客户端
if (write(fd, s, size) != size)
{
perror("write error");
}
}
int main(int argc, char *argv[])
{
if (argc < 2)
{
printf("usage:%s #port\n", argv[0]);
exit(1);
}
if (signal(SIGINT, sig_handler) == SIG_ERR)
{
perror("signal sigint error");
exit(1);
}
/*1. 创建socket
AF_INT:ipv4
SOCK_STREAM:tcp协议
*/
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
perror("socket error");
exit(1);
}
/*2:调用bind函数绑定socket和地址*/
struct sockaddr_in serveraddr;
memset(&serveraddr, 0, sizeof(serveraddr));
//往地址中填入ip,port,internet类型
serveraddr.sin_family = AF_INET; //ipv4
serveraddr.sin_port = htons(atoi(argv[1])); //htons主机字节序转成网络字节序
serveraddr.sin_addr.s_addr = INADDR_ANY;
if (bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
{
perror("bind error");
exit(1);
}
/*3:调用listen函数监听(指定port监听)
通知操作系统区接受来自客户顿的连接请求
第二个参数:指定队列长度
*/
if (listen(sockfd, 10) < 0)
{
perror("listen error");
}
std::cout << "I'm listening!" << std::endl;
/*4:调用accept函数从队列中获得一个客户端的请求连接
*/
struct sockaddr_in clientaddr;
socklen_t clientaddr_len = sizeof(clientaddr);
while (1)
{
int fd = accept(sockfd,
(struct sockaddr *)&clientaddr,
&clientaddr_len);
pid_t pid = fork();
if (pid == 0)
{
std::cout << "I'm a new process and my pid is " << getpid() << std::endl;
std::cout << "My parent process's pid is " << getppid() << std::endl;
if (fd < 0)
{
perror("accept error");
continue;
}
/*5:调用IO函数(read/write)和
连接的客户端进行双向通信
*/
out_addr(&clientaddr);
do_service(fd);
/*6.关闭socket*/
close(fd);
}
}
return 0;
}