tcp多线程处理多个客户端数据(linux)
thread 多线程 cpp
头文件需要加入
同时编译的时候,需要链接动态库 加入 -lpthread 参数
代表链接pthread.so库
链接动态库 需要-lxxxx参数
thread 执行
#include<thread>
// thread 线程名(指向函数的地址,指向对象的指针)
thread sth(&TcpThread::Main,thr)
逻辑
首先创建用于生成连接的socket
然后绑定端口号,接受的地址
for(;😉
{
accept() 接收到连接 生成用于单独连接的client_socket
然后 将这个client_socket 送至一个自创的对象中,用于交流信息
线程包裹该对象,
与子线程断开连接
}
代码
socket_test.cpp
// socket_test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <arpa/inet.h>
#include <iostream>
// 宏会在编译之前就执行,比如Linux时就不会有以下的代码
#ifdef WIN32 // 当存在WIN32的宏时,会执行中间的
#include <windows.h>
#else
#include <string.h>
#include <sys/types.h> /* linux 引用这两个*/
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <stdlib.h>
#endif
#include <thread>
using namespace std;
class TcpThread
{
public:
int client_sock=0;
TcpThread(int client_sock)
{
this->client_sock=client_sock;
}
~TcpThread()
{
delete this;
}
void Main()
{
char buf[1024]={0};
for(;;)
{
memset(buf,0,1024);
int rec_len = recv(client_sock,buf,sizeof(buf)-1,0);
cout<<rec_len<<endl;
buf[rec_len]='\0';
if(rec_len<=0)
{
break;
}
cout<<"recive_len:"<<rec_len<<endl;
cout<<"recive:"<<buf<<endl;
int sendlen=send(client_sock,buf,1024,0);
if(sendlen<=0)
{
break;
}
if(strstr(buf,"quit")!=NULL)
{
break;
}
}
// 需要留一位放'/0'
// 返回已经收到的数据大小,指定的大小不一定是实际接受的大小,只是指定最大收多少数据,必须返回
//
int rec_len = recv(client_sock,buf,sizeof(buf)-1,0);
cout<<"recive_len:"<<rec_len<<endl;
cout<<"recive:"<<buf<<endl;
#ifdef WIN32
closesocket(client_sock);
#else
close(client_sock);
#endif
// delete this;
}
};
int main(int argc,char* argv[])
{
unsigned short port=8080;
if (argc>1)
{
port=atoi(argv[1]);//atoi 字符串转化为数字
}
#ifdef WIN32 // 在linux中不需要以下的初始化
// windows 调用socket 库 ,需要1. 初始化动态库 2. 引用lib库
WSADATA ws;
WSAStartup(MAKEWORD(2, 2), &ws);//也加载动态库,引用加1
#endif
int sock=socket(AF_INET,SOCK_STREAM,0);//确定用什么协议,用tcp ip 小于0代表失败
if(sock<0)
{
cout<<"连接失败"<<endl;
return -1;
}
sockaddr_in saddr; //存取ip地址,port
saddr.sin_family=AF_INET; //tcp/ip协议
saddr.sin_port=htons(port); // 统一转化为大端存储(网络默认)
saddr.sin_addr.s_addr=htonl(0);//一个机器可能有多个ip,这里默认任意ip都可以接受
// socket 和 端口ip等信息绑定
if(bind(sock,(sockaddr*)&saddr,sizeof(saddr))!=0)
{
cout<<"绑定失败"<<endl;
return -2;
}
cout<<"绑定成功"<<endl;
//开始监听
listen(sock,10);
// int client_sock=accept(sock,0,0); //0代表不想知道对方的连接信息
// // 会返回一个新的socket,与这个用户单独进行通信的,每一个连接都会生成一个socket
// cout<<"client sock"<<client_sock<<endl;
for(;;)
{
// 获取 连接客户端的ip和端口号
sockaddr_in caddr;
socklen_t len=0;
int client_sock=accept(sock,(sockaddr*)&caddr,&len);
if(client_sock<=0)
{
break;
}
cout<<"client sock"<<client_sock<<endl;
string ip=inet_ntoa(caddr.sin_addr);
cout<<"client ip:"<<ip<<endl;
unsigned short cport=ntohs(caddr.sin_port);//把网络上转换成本地的,linux其实不需要
cout<<"client port:"<<cport<<endl;
// 创建一个线程
TcpThread* thr=new TcpThread(client_sock);
thread sth(&TcpThread::Main,thr);
sth.detach();//拆分,释放主线程所拥有子线程的资源
}
close(sock);
//需要传client_sock,
std::cout << "Hello World!\n";
std::cout << "Hello World!\n";
return 0;
}
Makefile
socket_t:socket_test.cpp
g++ socket_test.cpp -std=c++11 -lpthread -o socket_t
一个shell 开启服务
make
./socket_t
另一个 进行连接
telnet 10.112.146.228 8080
另一个再进行连接
telnet 10.112.146.228 8080