多线程与多进程实现tcp服务端

多线程

#include <iostream>
#include <stdlib.h>
#include "tcpsocket.hpp"

void *thr_start(void *arg)
{
    long fd = (long)arg;//arg是一个指针有8个字节空间long也有8个字节空间
    TcpSocket cli_sock;
    cli_sock.SetFd(fd);
    while(1) {
        //通过新获取的通信套接字与客户端进行通信
        std::string buf;
        if (cli_sock.Recv(&buf) == false) {
            cli_sock.Close();//通信套接字接收数据出错,关闭的是通信套接字
            pthread_exit(NULL);//exit是退出进程
        }
        printf("client say:%s\n", &buf[0]);
        std::cout << "server say:";
        fflush(stdout);
        buf.clear();
        std::cin >> buf;
        if (cli_sock.Send(buf) == false) {
            cli_sock.Close();
            pthread_exit(NULL);
        }
    }
    //循环退出则关闭套接字
    cli_sock.Close();
    return NULL;
}

int main(int argc, char *argv[])
{
    if (argc != 3) {
        printf("em:./tcp_srv 192.168.122.132 9000\n");
        return -1;
    }
    std::string ip = argv[1];
    uint16_t port = atoi(argv[2]);

    TcpSocket lst_sock;
    CHECK_RET(lst_sock.Socket());//创建套接字
    //#define CHECK_RET(q) if((q)==false){return -1;}
    //if (lst_sock.Socket() == false) {return -1;}
    CHECK_RET(lst_sock.Bind(ip, port));//绑定地址信息
    CHECK_RET(lst_sock.Listen());//开始监听
    while(1) {
        TcpSocket cli_sock;
        std::string cli_ip;
        uint16_t cli_port;
        //Accept类成员函数,使用的私有成员_sockfd就是lst_sock的私有成员
        //cli_sock取地址传入,目的是为了获取accept接口返回的通信套接字描述符
        bool ret = lst_sock.Accept(&cli_sock, &cli_ip, &cli_port);//获取新套接字
        if (ret == false) {
            //获取新连接失败,可以重新继续获取下一个
            continue;
        }
        printf("new connect:[%s:%d]\n", cli_ip.c_str(), cli_port);
        //-----------------------------------------------------
        pthread_t tid;
        //将通信套接字当作参数传递给线程,让线程与客户端进行通信
        //cli_sock是一个局部变量--循环完了这个资源就会被释放
        pthread_create(&tid, NULL, thr_start, (void*)cli_sock.GetFd());//线程
        pthread_detach(tid);//不关心线程返回值,分离线程,退出后自动释放资源
        //主线程不能关闭cli_sock套接字,因为多线程是共用描述符的
    }
    lst_sock.Close();
    return 0;
}

多进程:

#include <iostream>
#include <stdlib.h>
#include <signal.h>
#include <sys/wait.h>
#include "tcpsocket.hpp"

void sigcb(int signo) {
    //当子进程退出的时候就会像父进程发送SIGCHLD信号,回调这个函数
    //waitpid返回值>0表示处理了一个退出的子进程
    //waitpid<=0表示没有退出的子进程了
    while(waitpid(-1, 0, WNOHANG) > 0);//一次回调循环将退出的子进程全部处理
}
int main(int argc, char *argv[])
{
    if (argc != 3) {
        printf("em:./tcp_srv 192.168.122.132 9000\n");
        return -1;
    }
    std::string ip = argv[1];
    uint16_t port = atoi(argv[2]);

    signal(SIGCHLD, sigcb);
    TcpSocket lst_sock;
    CHECK_RET(lst_sock.Socket());//创建套接字
    //#define CHECK_RET(q) if((q)==false){return -1;}
    //if (lst_sock.Socket() == false) {return -1;}
    CHECK_RET(lst_sock.Bind(ip, port));//绑定地址信息
    CHECK_RET(lst_sock.Listen());//开始监听
    while(1) {
        TcpSocket cli_sock;
        std::string cli_ip;
        uint16_t cli_port;
        bool ret = lst_sock.Accept(&cli_sock, &cli_ip, &cli_port);//获取新套接字
        if (ret == false) {
            continue;
        }
        printf("new connect:[%s:%d]\n", cli_ip.c_str(), cli_port);
        //-------------------------------------------------
        pid_t pid = fork();
        if (pid == 0) {//子进程复制父进程--数据独有,代码共享
            //让子进程处理与客户端通信
            while(1) {
                std::string buf;
                if (cli_sock.Recv(&buf) == false) {
                    cli_sock.Close();//通信套接字接收数据出错,关闭的是通信套接字
                    exit(0);
                }
                printf("client:[%s:%d] say:%s\n", &cli_ip[0], cli_port, &buf[0]);
                std::cout << "server say:";
                fflush(stdout);
                buf.clear();
                std::cin >> buf;
                if (cli_sock.Send(buf) == false) {
                    cli_sock.Close();
                    exit(0);
                }
            }
            cli_sock.Close();
            exit(0);
        }
        //父子进程数据独有,都会具有cli_sock,但是父进程并不通信
        cli_sock.Close();//这个关闭对子进程没有影响,因为数据各自有一份
    }
    lst_sock.Close();
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值