1.一个服务器只能有一个客户端连接(下面代码)
tcp网络编程(基础)-****博客
2.一个服务器可以有多个客户端连接(多线程)
server端创建多个线程,每个线程与不同的client端建立连接。
-----这里只需要改变下TcpServer.hpp就行了
#pragma once
#include<iostream>
#include<pthread.h>
#include"Socket.hpp"
class TcpServer; //在ThreadData前声明,ThreadData才可以调用TcpServer,否则TcpServer未定义
class ThreadData
{
public:
ThreadData(Socket* s, TcpServer* t, std::string& clientip, uint16_t port)
:sockp(s)
,tcp_this(t)
,_clientip(clientip)
,_port(port)
{}
public:
Socket* sockp;
TcpServer* tcp_this;
std::string _clientip;
uint16_t _port;
};
class TcpServer
{
public:
TcpServer(uint16_t port) :_port(port), _listensocket(new TcpSocket())
{
_listensocket->BuildListenSocketMethod(_port, defaultbackflag); //设置为监听状态
}
static void* Thread_Run(void* args) //根据pthread_create的要求,这个函数的参数只能是void*,并且只有一个,所以用static
{
pthread_detach(pthread_self()); //将线程设置为分离状态,主线程就不用阻塞等待(join)子线程
ThreadData* td = static_cast<ThreadData*>(args);
char bufferin[1024];
while(true)
{
ssize_t n = recv(td->sockp->GetSockfd(), bufferin, sizeof(bufferin)-1, 0); //接收client发送的信息
//ssize_t n = (s->GetSockfd(), bufferin, sizeof(bufferin)-1);
if(n > 0)
{
bufferin[n] = 0;
std::string ret;
ret += td->_clientip;
ret += " ";
ret += std::to_string(td->_port);
std::cout << ret << " " << "client say#" << bufferin << std::endl;
}
else
{
break;
}
}
return nullptr;
}
void Loop()
{
//client的ip,port
std::string peerip;
uint16_t peerport;
while(true)
{
Socket* s = _listensocket->AcceptConnection(&peerip, &peerport); //服务端接收客户端发来的连接请求
if(s == nullptr) exit(0);
std::cout << "accept success" << std::endl;
//创建线程
pthread_t id;
ThreadData* td = new ThreadData(s, this, peerip, peerport);
pthread_create(&id, nullptr, Thread_Run, td); //我们传结构体给Thread_Run函数
//我们不能join去回收,我们采取将子线程分离(pthread_detach)方式
//原因:join会阻塞等待,如果有新的客户端想连接(connect)服务端,而server在join阻塞,并没有accept,导致connect失败
// ssize_t n = recv(s->GetSockfd(), bufferin, sizeof(bufferin)-1, 0); //接收client发送的信息
// //ssize_t n = (s->GetSockfd(), bufferin, sizeof(bufferin)-1);
// if(n > 0)
// {
// bufferin[n] = 0;
// std::string ret;
// ret += peerip;
// ret += " ";
// ret += std::to_string(peerport);
// std::cout << ret << " " << "client say#" << bufferin << std::endl;
// }
// else
// {
// break;
// }
}
}
~TcpServer()
{
delete _listensocket;
}
private:
int _port;
Socket* _listensocket;
};