-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpthread_test.cpp
More file actions
164 lines (150 loc) · 4.2 KB
/
pthread_test.cpp
File metadata and controls
164 lines (150 loc) · 4.2 KB
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/**
* ==================================================
* @file pthread_test.cpp
* @brief 使用pthread修改的并发echo_server
* @author ywj
* @date 2025-06-22 10:56
* @version 1.0
* @copyright Copyright (c) 2025 ywj. All Rights Reserved.
* ==================================================
*/
#include<pthread.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<stdio.h>
#include<signal.h>
#include<time.h>
#include<string.h>
#define BUFFER_SIZE 1024
#define MAX_WAIT_QUEUE 10
#define PORT 9090
bool ifThreadRun=false;
#define LOG_INFO(format, ...) \
do { \
time_t now = time(NULL); \
struct tm *tm_info = localtime(&now); \
char timestamp[20]; \
strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", tm_info); \
printf("[INFO %s] " format "\n", timestamp, ##__VA_ARGS__); \
} while (0)
#define LOG_ERROR(format, ...) \
do { \
time_t now = time(NULL); \
struct tm *tm_info = localtime(&now); \
char timestamp[20]; \
strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", tm_info); \
printf("[ERROR %s] " format "\n", timestamp, ##__VA_ARGS__); \
} while (0)
//全局变量
int listenFd;
//定义NT信号处理函数
void handler_SIGNT(int signo)
{
ifThreadRun=false;
close(listenFd);
}
//定义TERM信号处理函数
void handler_SIGTERM(int signo)
{
ifThreadRun=false;
close(listenFd);
}
//定义线程处理函数--传入的参数是客户端套接字描述符
void* threadFunc(void*arg)
{
if (arg==NULL)
{
pthread_exit(NULL);
return NULL;
}
char buffer[BUFFER_SIZE]={0};
int sockFd=*((int*)arg);
while(ifThreadRun)
{
int nread=recv(sockFd,buffer,BUFFER_SIZE,0);
if (nread==0)
{
//断开连接
close(sockFd);
sockaddr_in addr;
socklen_t addrLen=sizeof(addr);
getpeername(sockFd,(sockaddr*)&addr,&addrLen);
LOG_ERROR("a client disconnected from server-->%s:%d\n",inet_ntoa(addr.sin_addr),ntohs(addr.sin_port));
//退出线程
pthread_exit(NULL);
}
else if (nread>0)
{
//处理可读数据
sockaddr_in addr;
socklen_t addrLen=sizeof(addr);
getpeername(sockFd,(sockaddr*)&addr,&addrLen);
LOG_INFO("recv data from client%s:%d-->%s\n",inet_ntoa(addr.sin_addr),ntohs(addr.sin_port),buffer);
//echo
send(sockFd,buffer,nread,0);
memset(buffer,0,nread);
}
}
close(sockFd);
return NULL;
}
int main()
{
//注册信号处理
signal(SIGINT,handler_SIGNT);
signal(SIGTERM,handler_SIGNT);
//创建socket
listenFd=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (listenFd<0)
{
LOG_ERROR("create listenFd error!\n");
exit(1);
}
//定义地址结构体
sockaddr_in servAddr;
sockaddr_in clientAddr;
socklen_t sockLen=sizeof(clientAddr);
servAddr.sin_family=AF_INET;
servAddr.sin_addr.s_addr=htonl(INADDR_ANY);
servAddr.sin_port=htons(9090);
//设置套接字选项
int opt=-1;
// 设置地址可重用
setsockopt(listenFd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
// 设置端口复用(Linux 3.9+)
setsockopt(listenFd, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt));
//绑定地址
if (bind(listenFd,(sockaddr*)&servAddr,sizeof(servAddr))<0)
{
LOG_ERROR("bind error!\n");
exit(1);
}
//监听
if (listen(listenFd,MAX_WAIT_QUEUE)<0)
{
LOG_ERROR("listen error!\n");
close(listenFd);
exit(1);
}
ifThreadRun=true;
for (;;)
{
int clientFd=accept(listenFd,(sockaddr*)&clientAddr,&sockLen);
if (clientFd<0)
{
continue;
}
LOG_INFO("a new client connected to server success-->%s:%d\n",inet_ntoa(clientAddr.sin_addr),ntohs(clientAddr.sin_port));
//创建一个新线程处理该客户端的读写
pthread_t threadId;
if (pthread_create(&threadId,NULL,&threadFunc,(void*)&clientFd)==0)
{
LOG_INFO("thread %lu start work for client %d\n",threadId,clientFd);
}
}
return 0;
}