国外哪些做问卷的网站,建设主题网站一般要经历的顺序,广州市住房与城乡建设部网站,建设外国商城网站1.多进程版本
这里选择创建子进程#xff0c;让子进程再创建子进程。父进程等待子进程#xff0c;子进程的子进程处理业务逻辑。因为子进程是直接退出#xff0c;子进程的子进程变成孤儿进程被系统管理#xff0c;所以父进程在等待的时候不是阻塞等待的#xff0c;所以可…1.多进程版本
这里选择创建子进程让子进程再创建子进程。父进程等待子进程子进程的子进程处理业务逻辑。因为子进程是直接退出子进程的子进程变成孤儿进程被系统管理所以父进程在等待的时候不是阻塞等待的所以可以处理多条链接请求。或者可以忽略SIGCHID信号让子进程不需要等待。
服务端
pragma once #includeiostream
#includeunistd.h
#includesys/types.h
#includesys/socket.h
#includearpa/inet.h
#includenetinet/in.h
#includestring.h
#includefcntl.h
#includesignal.h
#includesys/wait.h#define DEF_PORT 8081class TcpSever
{private:int port;int listen_sock;//监听套接字public: TcpSever(int _portDEF_PORT):port(_port),listen_sock(-1){}void InitSever(){listen_socksocket(AF_INET,SOCK_STREAM,0);//IPV4流式套接if(listen_sock0){std::cerr监听套接字创建失败std::endl;exit(-1);}//绑定struct sockaddr_in local;memset(local,\0,sizeof(local));//初始化结构体local.sin_familyAF_INET;local.sin_porthtons(port);//主机转网络local.sin_addr.s_addrINADDR_ANY;//随机绑定服务器ipif(bind(listen_sock,(struct sockaddr*)local,sizeof(local))0){std::cerr绑定失败std::endl;exit(-2);}//建立链接
#define BACK_LOG 5if(listen(listen_sock,BACK_LOG)0){std::cerr链接失败std::endl;exit(-3);}}//获取链接void Loop(){//获取客户端信息struct sockaddr_in client;//signal(SIGCHID,hander);//hander是信号捕捉方法while(true){socklen_t lensizeof(client);//获取新链接int sockaccept(listen_sock,(struct sockaddr*)client,len);if(sock0){std::cerr接受链接失败std::endl;continue;//继续接受其他链接请求}//多进程处理多个客户端pid_t idfork();if(id0)//子进程{//子进程,与子进程的子进程不关心listen_sockclose(listen_sock);if(fork()0){exit(0);//子进程直接退出后子进程的子进程变为孤儿进程被守护进程接管不用等待了}//子进程的子进程,处理业务std::cout获取新连接成功! ip[inet_ntoa(client.sin_addr)] port[ntohs(client.sin_port)]std::endl;//整数ip转为字符ip形式,网络字节端口转化为本地端口//开始服务std::string CIpinet_ntoa(client.sin_addr);int CPortntohs(client.sin_port);Sever(sock,CIp,CPort);exit(0);}//不能使用阻塞等待可以使用信号机制忽略SIGCHID信号或者使用两次fork函数close(sock);//父进程不关心客户端的链接请求请求交给子进程做。waitpid(id,nullptr,0);//不会阻塞因为id进程创建完子进程会立即退出所以不会阻塞。}}void Sever(int sock,std::stringip,int port){char buff[1024];while(true){memset(buff,0,sizeof(buff));ssize_t ReadSizeread(sock,buff,sizeof(buff)-1);if(ReadSize0){buff[ReadSize]\0;//添加字符串结束标志std::coutClient[ip-port-port]# buffstd::endl;write(sock,buff,ReadSize);//向客户端写入数据}else if(ReadSize0){//对端关闭链接std::coutClient[ip-port-port]# 关闭std::endl;break;}else{std::cerrsock读取错误std::endl;break;}}std::cout服务终止std::endl;}~TcpSever(){if(listen_sock0){close(listen_sock);}}
};启动服务端
#includeTcp_Sever.h// Tcp_Sever portvoid User(char*name)
{std::coutname portstd::endl;
}int main(int argc,char*argv[])
{if(argc!2){User(argv[0]);exit(-1);}TcpSever*Severnew TcpSever(atoi(argv[1]));//将字符串形式的端口号转化为整数形式Sever-InitSever();Sever-Loop();return 0;
}客户端
#pragma once#includeiostream
#includeunistd.h
#includesys/types.h
#includesys/socket.h
#includenetinet/in.h
#includearpa/inet.h
#includestring
#includestring.hclass TcpClient
{private:std::string sev_ip;//服务器ipint sev_port;int sock;public:TcpClient(std::string _ip,int _sev_port):sev_ip(_ip),sev_port(_sev_port),sock(-1){}void InitClient(){socksocket(AF_INET,SOCK_STREAM,0);if(sock0){std::cerr创建套接字失败std::endl;exit(-1);}//客户端不需要绑定监听}//启动客户端void Start(){//向服务器发送链接//填充服务器信息struct sockaddr_in sever;memset(sever,0,sizeof(sever));sever.sin_familyAF_INET;sever.sin_porthtons(sev_port);//服务器开放的端口sever.sin_addr.s_addrinet_addr(sev_ip.c_str());//服务器的ip地址if(connect(sock,(struct sockaddr*)sever,sizeof(sever))0){//与服务器交互std::cout发送交互请求成功std::endl;Request(sock);}else{std::cerr交互失败std::endl;}}void Request(int Sock){std::string meg;while(true){std::cout输入信息#;std::cinmeg;char buff[1024];write(Sock,meg.c_str(),meg.size());//读取服务器发送的消息ssize_t ReadSizeread(sock,buff,sizeof(buff)-1);if(ReadSize0){buff[ReadSize]\0;}std::coutSever#buffstd::endl;}}~TcpClient(){if(sock0){close(sock);}}
};启动客户端
#includeTcp_Client.h// ./Tcp_Client ip portvoid User(char*name)
{std::coutname sever_ip sever_portstd::endl;
}int main(int argc,char*argv[])
{if(argc!3){User(argv[0]);exit(-1);}TcpClient*Clientnew TcpClient(argv[1],atoi(argv[2]));Client-InitClient();Client-Start();return 0;
}2.多线程版本
注意在类内部的成员函数调用类内非静态成员函数时会自动带this指针。而线程执行的函数要求void* Hander(void*)类型所以线程执行函数要用static修饰。
服务端
#pragma once #includeiostream
#includeunistd.h
#includesys/types.h
#includesys/socket.h
#includearpa/inet.h
#includenetinet/in.h
#includestring.h
#includefcntl.h
#includesignal.h
#includesys/wait.h
#includepthread.h#define DEF_PORT 8081//通信结构体
class Pragram{public:int sock;std::string ip;int port;Pragram(int _sock,std::string _ip,int _port):sock(_sock),ip(_ip),port(_port){}
};class TcpSever
{private:int port;int listen_sock;//监听套接字public: TcpSever(int _portDEF_PORT):port(_port),listen_sock(-1){}void InitSever(){listen_socksocket(AF_INET,SOCK_STREAM,0);//IPV4流式套接if(listen_sock0){std::cerr监听套接字创建失败std::endl;exit(-1);}//绑定struct sockaddr_in local;memset(local,\0,sizeof(local));//初始化结构体local.sin_familyAF_INET;local.sin_porthtons(port);//主机转网络local.sin_addr.s_addrINADDR_ANY;//随机绑定服务器ipif(bind(listen_sock,(struct sockaddr*)local,sizeof(local))0){std::cerr绑定失败std::endl;exit(-2);}//建立链接
#define BACK_LOG 5if(listen(listen_sock,BACK_LOG)0){std::cerr链接失败std::endl;exit(-3);}std::cout服务启动成功std::endl;}//获取链接void Loop(){//获取客户端信息struct sockaddr_in client;//signal(SIGCHID,hander);//hander是信号捕捉方法while(true){socklen_t lensizeof(client);//获取新链接int sockaccept(listen_sock,(struct sockaddr*)client,len);if(sock0){std::cerr接受链接失败std::endl;continue;//继续接受其他链接请求}pthread_t tid;std::string ipinet_ntoa(client.sin_addr);int portntohs(client.sin_port);Pragram*msgnew Pragram(sock,ip,port);pthread_create(tid,nullptr,HanderQuest,msg);}}private:static void* HanderQuest(void*arg){Pragram*msg(Pragram*)arg;pthread_detach(pthread_self());//线程分离std::cout获取新连接成功[ ip:msg-ip port:msg-port ]std::endl;Sever(msg-sock,msg-ip,msg-port);close(msg-sock);delete msg;return nullptr;}static void Sever(int sock,std::stringip,int port){char buff[1024];while(true){memset(buff,0,sizeof(buff));ssize_t ReadSizeread(sock,buff,sizeof(buff)-1);if(ReadSize0){buff[ReadSize]\0;//添加字符串结束标志std::coutClient[ip-port-port]# buffstd::endl;write(sock,buff,ReadSize);//向客户端写入数据}else if(ReadSize0){//对端关闭链接std::coutClient[ip-port-port]# 关闭std::endl;break;}else{std::cerrsock读取错误std::endl;break;}}std::cout服务终止std::endl;}~TcpSever(){if(listen_sock0){close(listen_sock);}}
};
客户端代码部分不变。 3.模板线程池版本
线程池代码
PthreadPool.h
#pragma once #includeiostream
#includepthread.h
#includequeue#define NUM 5templatetypename Task
class ThreadPool
{private:std::queueTask _task_queue;//临界资源pthread_mutex_t _lock;int _thread_num;pthread_cond_t _cond;public:ThreadPool(int NumNUM):_thread_num(Num){pthread_mutex_init(_lock,nullptr);pthread_cond_init(_cond,nullptr);}bool IsEmpty(){return _task_queue.empty();}static void*Routine(void*arg)//静态函数无隐含的this指针{pthread_detach(pthread_self());ThreadPoolTask*self(ThreadPoolTask*)arg;while(true){pthread_mutex_lock((self-_lock));while(self-IsEmpty())//循环检测临界资源是否就绪{//休眠pthread_cond_wait((self-_cond),(self-_lock));}//任务队列有任务Task t;self-Pop(t);pthread_mutex_unlock((self-_lock));//解锁后处理任务t.Run();}}void Push(const Taskin)//外部添加任务{pthread_mutex_lock(_lock);_task_queue.push(in);//唤醒一个线程pthread_cond_signal(_cond);pthread_mutex_unlock(_lock);}void Pop(Taskout)//线程获取任务{out_task_queue.front();_task_queue.pop();}~ThreadPool(){pthread_mutex_destroy(_lock);pthread_cond_destroy(_cond);}void InitThreadPool(){pthread_t tid;for(int i0;i_thread_num;i){//为了避免传参时C传this指针在线程执行方法上带static。//传参数时将this指针传到线程执行方法上。 pthread_create(tid,nullptr,Routine,this);}}
};设计任务Task.h #pragma once #includeiostream
#includestring
#includeunistd.h
#includestring.hstruct Hander{void operator()(int sock,std::stringip,int port){char buff[1024];while(true){memset(buff,0,sizeof(buff));ssize_t ReadSizeread(sock,buff,sizeof(buff)-1);if(ReadSize0){buff[ReadSize]\0;//添加字符串结束标志std::coutClient[ip-port-port]# buffstd::endl;write(sock,buff,ReadSize);//向客户端写入数据}else if(ReadSize0){//对端关闭链接std::coutClient[ip-port-port]# 关闭std::endl;break;}else{std::cerrsock读取错误std::endl;break;}}std::cout服务终止std::endl;close(sock);}
};class Task{private:int sock;std::string ip;int port;Hander condut;//仿函数public:Task()default;Task(int _sock,std::string _ip,int _port):sock(_sock),ip(_ip),port(_port){}void Run(){condut(sock,ip,port);}};服务端代码
#pragma once #includeiostream
#includeunistd.h
#includesys/types.h
#includesys/socket.h
#includearpa/inet.h
#includenetinet/in.h
#includestring.h
#includefcntl.h
#includesignal.h
#includesys/wait.h
#includepthread.h#includeThreadPool.h
#includeTask.h#define DEF_PORT 8081//通信结构体
class Pragram{public:int sock;std::string ip;int port;Pragram(int _sock,std::string _ip,int _port):sock(_sock),ip(_ip),port(_port){}
};class TcpSever
{private:int port;int listen_sock;//监听套接字ThreadPoolTask*Pool;public: TcpSever(int _portDEF_PORT):port(_port),listen_sock(-1),Pool(nullptr){}void InitSever(){listen_socksocket(AF_INET,SOCK_STREAM,0);//IPV4流式套接if(listen_sock0){std::cerr监听套接字创建失败std::endl;exit(-1);}//绑定struct sockaddr_in local;memset(local,\0,sizeof(local));//初始化结构体local.sin_familyAF_INET;local.sin_porthtons(port);//主机转网络local.sin_addr.s_addrINADDR_ANY;//随机绑定服务器ipif(bind(listen_sock,(struct sockaddr*)local,sizeof(local))0){std::cerr绑定失败std::endl;exit(-2);}//建立链接
#define BACK_LOG 5if(listen(listen_sock,BACK_LOG)0){std::cerr链接失败std::endl;exit(-3);}std::cout服务启动成功std::endl;Poolnew ThreadPoolTask(10);//10个线程}//获取链接void Loop(){Pool-InitThreadPool();//获取客户端信息struct sockaddr_in client;//signal(SIGCHID,hander);//hander是信号捕捉方法while(true){socklen_t lensizeof(client);//获取新链接int sockaccept(listen_sock,(struct sockaddr*)client,len);if(sock0){std::cerr接受链接失败std::endl;continue;//继续接受其他链接请求}std::string ipinet_ntoa(client.sin_addr);int portntohs(client.sin_port);Task asig(sock,ip,port);Pool-Push(asig);}}~TcpSever(){if(listen_sock0){close(listen_sock);}}
};客户端代码不需要改变