tcp多线程处理多个客户端数据(linux)

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
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值