前面的服务端只能在同一时间内处理一个客户端请求,而另外发起连接的客户端则会阻塞在accept队列中,等待正在服务的客户端退出直到轮到自己。这种仅能一对一处理的服务器在效率上是绝不可允许的,因此我们需要使得服务器能同时实现对多个用户的服务处理。
本文介绍第一种方法:阻塞IO+多线程并发(进程开销过大,不予考虑)
其原理在于server使用accpet轮询,得到客户端的套接字后交付给一个线程处理,之后重复轮询accept。
服务端
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/ioctl.h>
unsigned short server_Port = 1234; // 服务器端口
const char *IP = "192.168.80.132"; // 服务器IP
typedef struct client_info
{
struct sockaddr_in client_Addr;
int conn_Scoket;
} client_info;
/*字母转大写*/
void upper(char *buf)
{
char *pointer = buf;
while (*pointer != '\n')
{
if (*pointer >= 'a' && *pointer <= 'z')
*pointer -= 32;
pointer++;
}
return;
}
void handle_client(void *arg)
{
client_info client = *(client_info *)arg;
char *client_Ip = inet_ntoa(client.client_Addr.sin_addr);
int conn_Socket = client.conn_Scoket;
in_port_t client_Port = ntohs(client.client_Addr.sin_port);
printf("客户端: %s:%hu已连接!\n", client_Ip, client_Port);
while (1)
{
char buf[100];
memset(buf, '\0', 100);
int count = read(conn_Socket, buf, 99);
if (count == -1) // 若未有数据则返回报错
{
continue;
}
else if (count == 0)
{
printf("客户端: %s:%hu断开连接!\n", client_Ip, client_Port);
close(conn_Socket);
break;
}
else
{
printf("客户端: %s:%hu消息:%s", client_Ip, client_Port, buf);
upper(buf);
write(conn_Socket, buf, 99);
}
}
}
int main()
{
// 创建套接字
int server_Socket = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in server_Addr;
server_Addr.sin_family = AF_INET;
server_Addr.sin_port = htons(server_Port);
int flag = inet_aton(IP, &(server_Addr.sin_addr));
if (!flag)
{
perror("IP transfer failed!\n");
}
// 绑定服务器IP地址端口号
bind(server_Socket, (struct sockaddr *)&server_Addr, sizeof(server_Addr));
listen(server_Socket, 5);
while (1)
{
client_info client;
int addrlen = sizeof(struct sockaddr_in);
int conn_Socket = accept(server_Socket, (struct sockaddr *)&(client.client_Addr), &addrlen);
if (conn_Socket == -1)
{
break;
}
/*创建一个新线程*/
pthread_t new_thread;
client.conn_Scoket = conn_Socket;
pthread_create(&new_thread, NULL, handle_client, (void *)&client);
pthread_detach(new_thread);
}
pthread_exit(NULL); // 等待处理客户端的子线程完结后才退出
close(server_Socket);
return 0;
}
客户端可用第一篇
浙公网安备 33010602011771号