并发服务器应用于一个服务器可以同时相应多个客户端,具体步骤就是在一个循环里面,如果接受连接,就创建一个线程,然后在该线程函数里面完成对应的客户端要做的事
以下是普通TCP服务器和多线程并发服务器的代码
1.普通服务器:
#include
#include
#include
#include
#include /* See NOTES */
#include
#include
#include
int main()
{
//创建socket
int sockfd = socket(AF_INET, SOCK_STREAM, 0); //ipv4协议 流式套接字 具体的协议类型
if(-1 == sockfd)
{
perror("socket");
exit(1);
}
int opt = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); //地址可以被重复绑定
struct sockaddr_in server_addr; //保存服务器信息
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = 800;
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //回环ip,表示本机,测试的时候可以用
//绑定信息
int ret = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if(-1 == ret)
{
perror("bind");
exit (1);
}
//设置监听队列
ret = listen(sockfd, 10); //十个客户端可以与服务器连接
if(-1 == ret)
{
perror("listen");
exit(1);
}
printf("等待客户端的连接...\n");
struct sockaddr_in client_addr; //保存客户端信息
int length = sizeof(client_addr);
//接受连接(建立TCP连接)
int fd = accept(sockfd, (struct sockaddr *)&client_addr, &length);
if(-1 == fd)
{
perror("accept");
exit(2);
}
printf("接受客户端的连接 %d\n",fd);
char buf[32] = {0};
while(1)
{
//从fd接收消息,TCP相当于一个文件,fd就是文件描述符, 从fd读取数据,就是从TCP连接接收数据
ret = recv(fd, buf, sizeof(buf), 0);
if(-1 == ret)
{
perror("recv");
exit(1);
}
if(!strcmp(buf, "bye"))
{
break;
}
printf("%s\n",buf);
memset(buf, 0, sizeof(buf));
}
close(fd);
close(sockfd);
return 0;
}
2.多线程并发服务器
#include
#include
#include
#include
#include /* See NOTES */
#include
#include
#include
#include
void *ClientHandler(void *arg)
{
int ret;
int fd = *(int *)arg;
char buf[32] = {0};
pthread_detach(pthread_self()); //线程结束,自动释放资源;
while(1)
{
//从fd接收消息,TCP相当于一个文件,fd就是文件描述符, 从fd读取数据,就是从TCP连接接收数据
ret = recv(fd, buf, sizeof(buf), 0);
if(-1 == ret)
{
perror("recv");
exit(1);
}
if(0 == ret) //客户端异常退出
{
break;
}
if(!strcmp(buf, "bye"))
{
break;
}
printf("接收%d客户端%s\n",fd,buf);
memset(buf, 0, sizeof(buf));
}
printf("%d 客户端退出\n", fd);
close(fd);
}
int main()
{
//创建socket
int sockfd = socket(AF_INET, SOCK_STREAM, 0); //ipv4协议 流式套接字 具体的协议类型
if(-1 == sockfd)
{
perror("socket");
exit(1);
}
int opt = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); //地址可以被重复绑定
struct sockaddr_in server_addr; //保存服务器信息
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = 800;
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //回环ip,表示本机,测试的时候可以用
//绑定信息
int ret = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if(-1 == ret)
{
perror("bind");
exit (1);
}
//设置监听队列
ret = listen(sockfd, 10); //十个客户端可以与服务器连接
if(-1 == ret)
{
perror("listen");
exit(1);
}
printf("等待客户端的连接...\n");
struct sockaddr_in client_addr; //保存客户端信息
int length = sizeof(client_addr);
//接受连接(建立TCP连接)
while(1)
{
int fd = accept(sockfd, (struct sockaddr *)&client_addr, &length);
if(-1 == fd)
{
perror("accept");
exit(2);
}
printf("接受客户端的连接 %d\n",fd);
//为每一个客户端创建新的线程
pthread_t tid;
ret = pthread_create(&tid, NULL, ClientHandler, &fd);
if(ret != 0)
{
perror("pthread_create");
exit(1);
}
usleep(10000);
}
close(sockfd);
return 0;
}