基于多线程实现的并发服务器
#include <iostream>
#include <cstring>
#include <thread>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>using namespace std;struct SockInfo {int fd; pthread_t pid; sockaddr_in addr;
};SockInfo sock_infos[128];
sockaddr_in server_addr;int listenfd;bool InitServer(unsigned int port, unsigned int backlog) { listenfd = socket(AF_INET, SOCK_STREAM, 0); if (listenfd < 0) {perror("listensocket init failed");return false;}memset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(port);server_addr.sin_addr.s_addr = htonl(INADDR_ANY); int ret = bind(listenfd, (struct sockaddr*)&server_addr, sizeof(server_addr)); if (ret < 0) {perror("bind failed");return false;}ret = listen(listenfd, backlog);if (ret < 0) {perror("listen failed");return false;}return true;
}void* worker(void* arg) {SockInfo* pinfo = (SockInfo*)arg;cout<<"child thread, connfd: " << pinfo->fd << endl;while (true) {char buff[1024];memset(buff, 0, sizeof(buff));int ret = recv(pinfo->fd, buff, sizeof(buff), 0);if (ret == 0) {cout << "client disconnected" << endl;pinfo->fd = -1;break;} else if (ret == -1) {perror("recv failed");break;}cout << "receive msg: " << buff << endl;ret=send(pinfo->fd,buff,strlen(buff),0); if(ret==-1){perror("send failed");return 0;}cout<<"send msg: "<<buff<<endl;}close(pinfo->fd);pthread_exit(NULL);
}int main(int argc, char* argv[]) {if (argc < 2) {cerr << "Usage: " << argv[0] << " <port>" << endl;return EXIT_FAILURE;}unsigned int port = atoi(argv[1]);if (!InitServer(port, 5)) {exit(EXIT_FAILURE);}int max = sizeof(sock_infos) / sizeof(sock_infos[0]);for (int i = 0; i < max; i++) {memset(&sock_infos[i], 0, sizeof(sock_infos[i]));sock_infos[i].fd = -1;sock_infos[i].pid = -1;}SockInfo* pinfo;while (true) {int found = 0;for (int i = 0; i < max; i++) {if (sock_infos[i].fd == -1) {pinfo = &sock_infos[i];found = 1;break;}}if (!found) { int connfd = accept(listenfd, (struct sockaddr*)&pinfo->addr, (socklen_t*)&(pinfo->addr));if (connfd != -1) {char error_msg[] = "已达到连接数的最大值\n";send(connfd, error_msg, sizeof(error_msg) - 1, 0); close(connfd); continue;}}int connfd = accept(listenfd, (struct sockaddr*)&pinfo->addr, (socklen_t*)&(pinfo->addr));if (connfd == -1) {perror("accept failed");continue;}pinfo->fd = connfd;cout << "parent thread, connfd: " << connfd << endl;pthread_create(&pinfo->pid, NULL, worker, pinfo);pthread_detach(pinfo->pid); }close(listenfd);return 0;
}
#include <iostream>
#include <cstring>
#include <cstdio>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>using namespace std;int main(int argc,char *argv[])
{if(argc!=3){cout<<"Examples: ./demo1 服务端 端口号"<<endl;return -1;}int socketid=socket(AF_INET,SOCK_STREAM,0);if(socketid==-1){perror("socket error");return -1;}struct hostent* h; if((h=gethostbyname(argv[1]))==0){perror("gethostbyname error");close(socketid);return -1;}struct sockaddr_in serveraddr;memset(&serveraddr,0,sizeof(serveraddr));serveraddr.sin_family=AF_INET;serveraddr.sin_port=htons(atoi(argv[2]));if(connect(socketid,(struct sockaddr*)&serveraddr,sizeof(serveraddr))==-1){perror("connect error");close(socketid);return -1;}int iret;char buffer[1024];memset(buffer,0,sizeof(buffer));for(int i=1;i<10;i++){sprintf(buffer,"这是第%d份报文",i);if((iret=send(socketid,buffer,strlen(buffer),0))==-1){perror("send error");close(socketid);break;}sleep(10);cout<<"发送成功"<<endl;memset(buffer,0,sizeof(buffer));if((iret=recv(socketid,buffer,sizeof(buffer),0))==-1){perror("recv error");close(socketid);break;}cout<<"接收成功"<<endl;}close(socketid);cout<<"连接已断开"<<endl;return 0;
}
```