实验三、基于流式套接字的多线程并发服务器回射程序设计
0x00 实验内容
将 实验二 中的服务器改为并发服务器。
0x01 实现过程
实现方法
这个和 实验二 中的代码只差一部分——只需要让服务器开一个线程单独为当前客户服务即可。我这里是使用 pthread.h 来实现创建线程的。
公共函数中修改部分
// comm.h
// 在实验二的基础上添加如下内容
#include <pthread.h>
void *asyncTcpEchoServer(LPVOID pParam)
{
int sock_res;
char recv_data[MAXLINE];
// 将输入参数转换成连接套接字
SOCKET sock_conn = *((SOCKET *)pParam);
do
{
memset(recv_data, 0, MAXLINE);
// 接收数据
sock_res = recv(sock_conn, recv_data, MAXLINE, 0);
if (sock_res > 0)
{
cout << "The Data Received From Client Is:" << recv_data << endl;
// 回射接收的数据
sock_res = send(sock_conn, recv_data, sock_res, 0);
if (sock_res == SOCKET_ERROR)
{
cout << WSAGetLastError() << "Send Error!" << endl;
sock_res = -1;
}
else
{
cout << "The Data Sent From Server Is:" << recv_data << endl;
}
}
else
{
if (sock_res == 0)
{
cout << "Client is closed!" << endl;
}
else
{
cout << WSAGetLastError() << "Recv Error!" << endl;
sock_res = -1;
}
break;
}
} while (sock_res > 0);
if (sock_res == -1)
{
cout << "Disconnected or Sth. Error" << endl;
}
return nullptr;
}
Server 端
// server.cpp
#include "comm.h"
int main(int argc, char *argv[])
{
int res = -1;
SOCKET sock_conn;
SOCKET sock_listen;
pthread_t pThread;
char buff[MAXLINE]; //缓冲区
// 启动
res = startUp();
if (res == -1) return -1;
//监听
sock_listen = tcpServer(SEVER_PORT);
if (sock_listen == -1) return -1;
cout << "Server Start!" << endl;
while (true)
{
//接受客户端连接请求,返回连接套接字sock_conn
sock_conn = accept(sock_listen, nullptr, nullptr);
if (sock_conn != INVALID_SOCKET)
{
cout << "Conn Success!" << endl;
// 创建线程
pthread_create(&pThread, nullptr, asyncTcpEchoServer, &sock_conn);
}
else
{
cout << WSAGetLastError() << "Accept Error!" << endl;
closeConn(sock_listen);
return -1;
}
}
// 关闭连接
closeConn(sock_listen);
return 0;
}
Client 端无需改动
附:某些情况下可以考虑使用 select 来实现并发,用select在一些场景下可以有效解决线程膨胀问题。
版权声明:本文为AnonymKing原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。