Linux下socket编程基础2-初探(完善云服务器上的代码)

完善云服务器的代码

自己搭建一个客户端和服务器一对一的通信的收发demo。后续研究如何让服务器连接更多客户端,以及继续完善代码。

上一次的程序

  • demo的思路是利用四个线程分别处理收信息,发信息,保持连接状态稳定,以及异常处理。尚未实现
  • 目前只是连上服务器后隔10秒发送10条信息测试
  • 客户端是用QT写的调试助手,只实现了部分功能。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
#include <string>
#include <string.h>
#include <vector>
#include <queue>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <netinet/in.h>
#include <pthread.h>

using namespace std;

//初始化发送数据缓冲区
char Sendbuf[2048]={0};
struct iovec Sbuffer={
    .iov_base = Sendbuf,
    .iov_len = sizeof(Sendbuf)
};
struct msghdr MySmsg={
    .msg_name = nullptr,
    .msg_namelen =0,
    .msg_iov = &Sbuffer,
    .msg_iovlen = 1,
    .msg_control = nullptr,
    .msg_controllen = 0,
    .msg_flags = 0
};

//初始化接收数据缓冲区
char Recvbuf[2048]={0};
struct iovec Rbuffer={
    .iov_base = Recvbuf,
    .iov_len = sizeof(Recvbuf)
};
struct msghdr MyRmsg={
    .msg_name = nullptr,
    .msg_namelen =0,
    .msg_iov = &Rbuffer,
    .msg_iovlen = 1,
    .msg_control = nullptr,
    .msg_controllen = 0,
    .msg_flags = 0
};

vector<pthread_t> thread_box(4,0);
/*{
    第一个线程:异常处理线程
    第二个线程:保持心跳、监控连接状态线程
    第三个线程:信息接收线程
    第四个线程:信息发送线程
  }*/
vector<pthread_mutex_t> mut_box(2);
/*{
    第一个互斥锁:异常状态处理锁
    第二个互斥锁:暂时未定
  }*/
int ServerSocketID = 0;
int ClientSocketID = 0;

auto sendMessageBox = new queue<string>;
auto recvMessageBox = new queue<string>;

void thread_create(void);
int ServerInit(void);
int WaitClientConnect(int ServerSocket);

void *RecvMessageThread(void*);
void *SendMessageThread(void*);
void *KeepConnectThread(void*);
void *ExceptionHandlerThread(void*);

void thread_create(void){
    int res;
    res = pthread_create(&thread_box[0],nullptr,ExceptionHandlerThread,nullptr);
    if(!res) cout << "ExceptionHandlerThread Create succ" << endl;
    res = pthread_create(&thread_box[1],nullptr,KeepConnectThread,nullptr);
    if(!res) cout << "KeepConnectThread Create succ" << endl;
    res = pthread_create(&thread_box[2],nullptr,SendMessageThread,nullptr);
    if(!res) cout << "SendMessageThread Create succ" << endl;
    res = pthread_create(&thread_box[3],nullptr,RecvMessageThread,nullptr);
    if(!res) cout << "RecvMessageThread Create succ" << endl;
}

int ServerInit(void){//socket初始化并等待连接
    //创建套接字
    int Mysocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    //将套接字和IP、端口绑定
    struct sockaddr_in Server_Addr;
    memset(&Server_Addr,0,sizeof(Server_Addr));
    Server_Addr.sin_family=AF_INET; //设置使用ipv4地址
    Server_Addr.sin_addr.s_addr=inet_addr("***.***.***.***");//设置具体的ip地址
    Server_Addr.sin_port=htons(12345); //端口
    bind(Mysocket,(struct sockaddr *)&Server_Addr,sizeof(Server_Addr));
 
    //进入监听状态
    listen(Mysocket,10);

    return Mysocket;
}

int WaitClientConnect(int ServerSocket){
    //接收客户端请求
    struct sockaddr_in client_addr;
    socklen_t client_size = sizeof(client_addr);
    // std::cout << "ready to accept!...."<<endl;
    int client_sock = accept(ServerSocket,(struct sockaddr*)&client_addr,&client_size);//在此阻塞
    //std::cout << "accept finish!.."<<endl;
    //向客户端发送连接标志
    char str[] = "hello,wellcome! from : 120.79.73.84";
 
    MySmsg.msg_iov->iov_base = str;
 
    sendmsg(client_sock,&MySmsg,0); //write(client_sock,str,sizeof(str));用write也是可以的
 
    memset(&Sendbuf,0,sizeof(Sendbuf));
    return client_sock;
} 
 
int main(int argc, char **argv){
    for(int i=0,len=mut_box.size();i<len;++i){
        pthread_mutex_init(&mut_box[i],nullptr);
    }
    pthread_mutex_lock(&mut_box[0]);
    ServerSocketID = ServerInit();
    ClientSocketID = WaitClientConnect(ServerSocketID);
    thread_create();
    while(1);
    return 0;
}

void *RecvMessageThread(void*){
    pthread_detach(pthread_self());
    while(1){
        recvmsg(ClientSocketID,&MyRmsg,0);
        string str_cpp = (char*)MyRmsg.msg_iov->iov_base;
        if(str_cpp.size()!=0){
            cout << str_cpp << endl;
        }
        memset(&Recvbuf,0,sizeof(Recvbuf));
        sleep(1);
    }
}

void *SendMessageThread(void*){
    pthread_detach(pthread_self());
    while(1){
        while(!sendMessageBox->empty()){
            string str = sendMessageBox->front();
            sendMessageBox->pop();
            MySmsg.msg_iov->iov_base = (void*)str.c_str();
            sendmsg(ClientSocketID,&MySmsg,0);
            memset(&Sendbuf,0,sizeof(Sendbuf));
        }
        sleep(1);
    }
}

void *KeepConnectThread(void*){
    pthread_detach(pthread_self());
    while(1){
        string str = "This is Heartbeat!";
        for(int i=0;i<5;i++){
            sendMessageBox->push(str);
            sleep(10);
        }
        pthread_mutex_unlock(&mut_box[0]); //释放锁,结束
    }
}

void *ExceptionHandlerThread(void*){//结束
    pthread_detach(pthread_self());

    pthread_mutex_lock(&mut_box[0]);

    pthread_cancel(thread_box[1]);
    pthread_cancel(thread_box[2]);
    pthread_cancel(thread_box[3]);

    close(ClientSocketID);
    close(ServerSocketID);

    pthread_mutex_unlock(&mut_box[0]);

    pthread_exit(0);
}
  • 使用cmake工程化编译,由于使用了pthread需要链接pthread库,所以cmake有所改变
/***CMakeLists.txt***/
cmake_minimum_required(VERSION 3.10.2)
 
PROJECT(mysocket)
SET(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-std=c++11 -pthread")
find_package (Socket)
add_executable(Mysocket Mysocket.cpp)
target_link_libraries (Mysocket ${CMAKE_THREAD_LIBS_INIT})
运行效果
效果图
posted @ 2020-09-23 15:27  JoyooO  阅读(132)  评论(0编辑  收藏  举报