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})