(1)多线程并发服务器server.c
//使用pthread线程库 #include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <pthread.h> #include <stdlib.h> #define PORT 1234 //服务器端口 #define BACKLOG 5 //listen队列等待的连接数 #define MAXDATASIZE 1024 //缓冲区大小 void process_cli(int connectfd, struct sockaddr_in client); //客户端请求处理函数 void* start_routine(void* arg); //线程函数 typedef struct _ARG { int connfd; struct sockaddr_in client; }ARG; //客户端结构体 void main() { int listenfd, connectfd; //socket描述符 pthread_t thread; //线程体变量 ARG *arg; //客户端结构体变量 struct sockaddr_in server; //服务器地址信息结构体 struct sockaddr_in client; //客户端地址信息结构体 int sin_size; if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { //调用socket,创建监听客户端的socket perror("Creating socket failed."); exit(1); } int opt = SO_REUSEADDR; setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); //设置socket属性,端口可以重用 //初始化服务器地址结构体 bzero(&server,sizeof(server)); server.sin_family=AF_INET; server.sin_port=htons(PORT); server.sin_addr.s_addr = htonl (INADDR_ANY); if (bind(listenfd, (struct sockaddr *)&server, sizeof(struct sockaddr)) == -1) { //调用bind,绑定地址和端口 perror("Bind error."); exit(1); } if(listen(listenfd,BACKLOG) == -1){ //调用listen,开始监听 perror("listen() error\n"); exit(1); } sin_size=sizeof(struct sockaddr_in); while(1) { if ((connectfd = accept(listenfd,(struct sockaddr *)&client,(socklen_t *)&sin_size))==-1) { //调用accept,返回与服务器连接的客户端描述符 perror("accept() error\n"); exit(1); } arg = new ARG; arg->connfd = connectfd; memcpy(&arg->client, &client, sizeof(client)); if (pthread_create(&thread, NULL, start_routine, (void*)arg)) { //创建线程,以客户端连接为参数,start_routine为线程执行函数 perror("Pthread_create() error"); exit(1); } } close(listenfd); //关闭监听socket } void process_cli(int connectfd, sockaddr_in client) { int num; char recvbuf[MAXDATASIZE], sendbuf[MAXDATASIZE], cli_name[MAXDATASIZE]; printf("You got a connection from %s. ",inet_ntoa(client.sin_addr) ); num = recv(connectfd, cli_name, MAXDATASIZE,0); if (num == 0) { close(connectfd); printf("Client disconnected.\n"); return; } cli_name[num - 1] = '\0'; printf("Client's name is %s.\n",cli_name); while (num = recv(connectfd, recvbuf, MAXDATASIZE,0)) { recvbuf[num] = '\0'; printf("Received client( %s ) message: %s",cli_name, recvbuf); for (int i = 0; i < num - 1; i++) { sendbuf[i] = recvbuf[num - i -2]; } sendbuf[num - 1] = '\0'; send(connectfd,sendbuf,strlen(sendbuf),0); } close(connectfd); } void* start_routine(void* arg) { ARG *info; info = (ARG *)arg; process_cli(info->connfd, info->client); delete info; pthread_exit(NULL); }
客户端:
#include <iostream> using namespace std; string m_strIP = "172.168.1.242"; int m_nPort = 15003; void main() { int fd; int retcode; int recv_count; char *rcvbuf; struct sockaddr_in addr; struct timeval timeo = {10, 0}; unsigned long flags; memset(&addr,0x00,sizeof(struct sockaddr_in)); fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr(m_strIP); addr.sin_port = htons(m_nPort); //flags = fcntl(fd, F_GETFL, 0); //fcntl(fd, F_SETFL, flags | O_NONBLOCK); retcode = connect(fd, (struct sockaddr*)&addr, sizeof(addr)); recv_count = recv(fd, rcvbuf, 26, 0); cout<<recv_count<<endl; cout<<rcvbuf<<endl if(0 == retcode) { if (fcntl(fd, F_SETFL, flags) < 0) { cout<<"Connect error!"<<endl; return -1; } else { cout<<"Connect ok sockfd!"<<endl; return fd; } } }
(2)select非阻塞服务器
select单线程服务器:
#include <iostream> #include <sys/types.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <fcntl.h> #include <netinet/in.h> #include <arpa/inet.h> const int MAX_CLIENT = 40; using namespace std; int main() { int m_nSocket; sockaddr_in m_stSockaddr; string m_strIP = "172.168.1.242"; int m_nPort = 15003; m_nSocket = socket(AF_INET, SOCK_STREAM, 0); if (m_nSocket < 0) { cout<<"Create failed!"<<endl; return 1; } cout<<"socket succed!"<<endl; fcntl(m_nSocket, F_SETFL, O_NONBLOCK); //设置socket非阻塞 int nTmp = 1; int nRet =setsockopt(m_nSocket, SOL_SOCKET, SO_REUSEADDR, &nTmp, sizeof(int)); if (nRet < 0) { return 1; } cout<<"fcntl succed!"<<endl; // 设置SOCKET接收地址和端口 memset (&m_stSockaddr, 0, sizeof(m_stSockaddr)); m_stSockaddr.sin_family = AF_INET; m_stSockaddr.sin_addr.s_addr = inet_addr(m_strIP.c_str()); m_stSockaddr.sin_port = htons (m_nPort); nRet = bind (m_nSocket, (struct sockaddr*)&m_stSockaddr,sizeof(m_stSockaddr)); if (nRet < 0) { return 1; } cout<<"bind succed!"<<endl; nRet = listen (m_nSocket, MAX_CLIENT); if (nRet < 0) { return 1; } cout<<"listen succed!"<<endl; fd_set readfds; fd_set rdfds; struct timeval tv; sockaddr_in clientAddr; tv.tv_sec=60; // select超时时间 tv.tv_usec=0; int clientfd; FD_ZERO(&readfds); FD_ZERO(&rdfds); FD_SET(m_nSocket, &readfds); while(1) { cout<<"connecting........."<<endl; rdfds = readfds; nRet=select(m_nSocket+1, &rdfds, NULL, NULL, &tv); if(nRet > 0) { if(FD_ISSET(m_nSocket, &readfds)) { clientfd = accept(m_nSocket, (struct sockaddr*)&clientAddr, &sizeof(clientAddr)); if(clientfd<0) { cout<<"accept error!"<<endl; continue; } else if(send (clientfd,"Hello,you are connected!\n",26,0) != -1) { cout<<"send succedd"<<endl; } close(clientfd); } } } return 0; }
select多线程服务器:
select服务器:
socket_server.h(头文件):
#ifndef _SOCKET_SERVER_H_ #define _SOCKET_SERVER_H_ #include <iostream> #include <errno.h> #include <stdio.h> using namespace std; struct thread_param { void *t_this; int sockd; }; class socket_server { public: socket_server(); virtual ~socket_server(); void socket_op(); void *sock_thread(); private: void my_err(const char*err_string, char *function, int line); int sock_array[10000]; int nSock; int maxfd; }; #endifs ocket_server.cpp:
#include "socket_server.h" #include <pthread.h> #include <sys/time.h> #include <sys/select.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <fcntl.h> socket_server::socket_server() { memset(sock_array, 0, sizeof(sock_array)); nSock = 0; } socket_server::~socket_server() { } void *sock_thread_proc(void *arg) { pthread_detach(pthread_self()); socket_server *p_sock = (socket_server *)arg; p_sock->sock_thread(); return ((void *)0); } void *socket_server::sock_thread() { struct timeval tv; //gettimeofday(&tv, NULL); tv.tv_sec=10; // select超时时间 tv.tv_usec=0; fd_set readfds; fd_set writefds; FD_ZERO(&readfds); FD_ZERO(&writefds); int nRet; int ret; int i,j; char recv_buf[128] = {0}; while(1) { if (nSock == 0) { sleep(4); cout<<"nsock is zero"<<endl; continue; } maxfd = sock_array[0]; FD_SET(sock_array[0], &readfds); for (i = 1; i< nSock; i++) { FD_SET(sock_array[i], &readfds); if (sock_array[i] > maxfd) maxfd = sock_array[i]; } cout<<"maxfd:"<<maxfd<<endl; nRet=select(maxfd + 1, &readfds, NULL, NULL, &tv); if(nRet>0) { for (i = 0; i < nSock; i++) { if (FD_ISSET(sock_array[i], &readfds)) { if ((ret = recv(sock_array[i], recv_buf, sizeof(recv_buf), 0)) < 0) my_err("recv", __FUNCTION__, __LINE__); if (ret > 0) { recv_buf[ret] = '\0'; cout<<"server接受数据:"<<recv_buf<<endl; } else cout<<"server无数据。"<<endl; FD_SET(sock_array[i], &writefds); nRet=select(sock_array[i] + 1, NULL, &writefds, NULL, &tv); if(nRet > 0) { if (FD_ISSET(sock_array[i], &writefds)) { char *send_data = "接受数据成功!"; if (send(sock_array[i], send_data, strlen(send_data), 0) < 0){ my_err("send", __FUNCTION__, __LINE__); } cout<<"send succeed"<<endl; } } else cout<<"发送超时!"<<endl; //关闭该套接字 close(sock_array[i]); for (j = i; j < nSock - 1; j++) { sock_array[j] = sock_array[j + 1]; } nSock--; } } } else { cout<<"接收超时!"<<endl; break; } cout<<"******deal sock finish******"<<endl; } return ((void *)0); } void socket_server::my_err(const char*err_string, char *function, int line) { fprintf(stderr, "func[%s]line:%d\n", function, line); perror(err_string); exit(1); } void socket_server::socket_op() { pthread_t pid; pthread_create(&pid, NULL, sock_thread_proc, this); int sock_fd; int new_sockfd; struct sockaddr_in serv_addr; struct sockaddr_in client_addr; int nRet; int i; sock_fd = socket(AF_INET, SOCK_STREAM, 0); if (sock_fd < 0) my_err("socket", __FUNCTION__, __LINE__); fcntl(sock_fd, F_SETFL, O_NONBLOCK); //设置socket非阻塞 int optval = 1; //可以重新绑定端口 if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (void *)&optval, sizeof(int)) < 0) my_err("setsockopt", __FUNCTION__, __LINE__); memset(&serv_addr, 0, sizeof(struct sockaddr_in)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(4507); serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); nRet = bind(sock_fd, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr_in)); if (nRet < 0) my_err("bind", __FUNCTION__, __LINE__); nRet = listen(sock_fd, 10000); if (nRet < 0) my_err("listen", __FUNCTION__, __LINE__); fd_set readfds; FD_ZERO(&readfds); struct timeval tv; //gettimeofday(&tv, NULL); tv.tv_sec = 10; // select超时时间 tv.tv_usec=0; socklen_t addr_len = sizeof(struct sockaddr_in); while(1) { FD_SET(sock_fd, &readfds); nRet=select(sock_fd + 1, &readfds, NULL, NULL, &tv); if(nRet > 0) { if (FD_ISSET(sock_fd, &readfds)) { new_sockfd = accept(sock_fd, (struct sockaddr*)&client_addr, &addr_len); sock_array[nSock++] = new_sockfd; //入数组 } } else if(nRet == 0) { cout<<"waiting for connecting......"<<endl; continue; } else { cout<<"select error!"<<endl; } } } int main() { socket_server *obj = new socket_server(); cout<<"******socket server begin to accept client******"<<endl; obj->socket_op(); delete obj; return 0; }select客户端:
#ifndef _SOCKET_CLIENT_H_ #define _SOCKET_CLIENT_H_ #include <iostream> #include <errno.h> #include <stdio.h> #include <stdlib.h> using namespace std; class socket_client { public: socket_client(); virtual ~socket_client(); void socket_connect(const int conn_timeout); private: void my_err(const char*err_string, char *function, int line); }; #endifsocket_client.cpp:
#include "socket_client.h" #include <pthread.h> #include <sys/time.h> #include <sys/select.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <fcntl.h> #include <arpa/inet.h> socket_client::socket_client() { } socket_client::~socket_client() { } void socket_client::my_err(const char*err_string, char *function, int line) { fprintf(stderr, "func[%s]line:%d\n", function, line); perror(err_string); exit(1); } void socket_client::socket_connect(const int conn_timeout) { int sock_fd; int nRet; struct sockaddr_in addr; fd_set rdset; fd_set wtset; int retval; char sndbuff[1024] = "socket connnect to the server succeed."; char recv_buf[1024] = {0}; sock_fd = socket(AF_INET, SOCK_STREAM, 0); if (sock_fd < 0) my_err("socket", __FUNCTION__, __LINE__); addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr("127.0.0.1"); addr.sin_port = htons(4507); if (fcntl(sock_fd, F_SETFL, fcntl(sock_fd, F_GETFL) | O_NONBLOCK) < 0) { my_err("fcntl", __FUNCTION__, __LINE__); } nRet = connect(sock_fd, (struct sockaddr*)&addr, sizeof(addr)); if (nRet < 0) { my_err("fcntl", __FUNCTION__, __LINE__); } FD_ZERO(&wtset); FD_SET(sock_fd, &wtset); struct timeval tv; tv.tv_sec = conn_timeout; // select超时时间 tv.tv_usec = 0; retval = select(sock_fd + 1, NULL, &wtset, NULL, &tv); if (retval == 0) { cout<<"send timeout......"<<endl; } else if (retval > 0) { if(FD_ISSET (sock_fd, &wtset)) { if (send(sock_fd, sndbuff, strlen(sndbuff), 0) < 0) my_err("send", __FUNCTION__, __LINE__); cout<<"send succeed!"<<endl; } } FD_ZERO(&rdset); FD_SET(sock_fd, &rdset); retval = select(sock_fd + 1, &rdset, NULL, NULL, &tv); if (retval == 0) { cout<<"recv timeout......"<<endl; } else if (retval > 0) { if(FD_ISSET (sock_fd, &rdset)) { if ((retval = recv(sock_fd, recv_buf, sizeof(recv_buf), 0)) < 0) my_err("recv", __FUNCTION__, __LINE__); recv_buf[retval] = '\0'; cout<<"server接受数据:"<<recv_buf<<endl; } } close(sock_fd); } int main() { socket_client *obj = new socket_client(); obj->socket_connect(10); delete obj; return 0; }(3)pool非阻塞服务器和客户端
#ifndef _SOCKET_SERVER_H_ #define _SOCKET_SERVER_H_ #include <iostream> #include <errno.h> #include <stdio.h> #include <poll.h> using namespace std; struct thread_param { void *t_this; int sockd; }; class socket_server { public: socket_server(); virtual ~socket_server(); void socket_op(); void *sock_thread(); void sock_recvsend(int sockfd); private: void my_err(const char*err_string, char *function, int line); int sock_array[10000]; int nSock; int maxfd; struct pollfd fds[10000]; }; #endifsocket_server.cpp:
#include "socket_server.h" #include <pthread.h> #include <sys/time.h> #include <sys/select.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <fcntl.h> #include <poll.h> socket_server::socket_server() { pthread_mutex_init(&m_mutex, NULL); pthread_mutex_init(&m_lock, NULL); pthread_cond_init(&c_lock, NULL); memset(sock_array, 0, sizeof(sock_array)); nSock = 0; } socket_server::~socket_server() { pthread_mutex_destroy(&m_mutex); pthread_mutex_destroy(&m_lock); pthread_cond_destroy(&c_lock); } void *sock_thread_proc(void *arg) { pthread_detach(pthread_self()); socket_server *p_sock = (socket_server *)arg; p_sock->sock_thread(); return ((void *)0); } void *sock_recvsend_proc(void *arg) { pthread_detach(pthread_self()); thread_param *p_arg = (thread_param *)arg; socket_server *p_sock = (socket_server *)p_arg->t_this; p_sock->sock_recvsend(p_arg->sockd); delete p_arg; return ((void *)0); } void socket_server::sock_recvsend(int sockfd) { char sndbuff[32767] = {0}; int timeout = 10*1000; int ret; int nRet; int count; char recv_buf[32767] = {0}; FILE *fp = fopen("./body.txt", "r+"); fseek(fp, 0, SEEK_END); int len = ftell(fp); fseek(fp, 0, SEEK_SET); fread(sndbuff, 1, len, fp); while(1) { struct pollfd event; memset(&event, 0, sizeof(event)); event.fd = sockfd; event.events = POLLIN; recv_continue: nRet = poll((struct pollfd*)&event, 1, timeout); if (nRet < 0) { printf("poll error!\n"); exit(1); } else if (nRet > 0){ //有事件发生 if (event.revents & POLLIN) { if ((ret = recv(event.fd, recv_buf, sizeof(recv_buf), 0)) < 0) my_err("recv", __FUNCTION__, __LINE__); if (ret == 0) { cout<<"out"<<endl; break; } cout<<"server接受数据:"<<ret<<":"<<strlen(recv_buf)<<endl; recv_buf[ret] = '\0'; if(strstr(recv_buf,"Envelope>") == NULL){ goto recv_continue; } } memset(&event, 0, sizeof(event)); event.fd = sockfd; event.events = POLLOUT; send_continue: nRet = poll((struct pollfd*)&event, 1, timeout); if (nRet > 0) { if (event.revents & POLLOUT) { if ((count = send(event.fd, sndbuff, strlen(sndbuff), 0)) < 0){ my_err("send", __FUNCTION__, __LINE__); } cout<<"count:"<<count<<endl; if (count < len) { len = len - count; goto send_continue; } } } else { cout<<"发送超时!"<<endl; } } else if(nRet == 0) { cout<<"waiting for connecting123......"<<endl; continue; } else { cout<<"poll error!"<<endl; } } close(sockfd); } void *socket_server::sock_thread() { int timeout = 10*1000; int nRet; int i,j; while(1) { pthread_mutex_lock(&m_mutex); int num = nSock; pthread_mutex_unlock(&m_mutex); while (nSock == 0) { pthread_mutex_lock(&m_lock); pthread_cond_wait(&c_lock, &m_lock); pthread_mutex_unlock(&m_lock); } memset(fds, 0, sizeof(struct pollfd)*10000); for (i = 0; i < nSock; i++) { fds[i].fd = sock_array[i]; fds[i].events = POLLIN; } nRet = poll(fds, nSock, timeout); if (nRet < 0) { printf("poll error!\n"); exit(1); } else if (nRet > 0){ //有事件发生 for (i = 0; i < nSock; i++) { if (fds[i].revents & POLLIN) { pthread_t pid; thread_param *param = new thread_param(); param->t_this = this; param->sockd = fds[i].fd; pthread_create(&pid, NULL, sock_recvsend_proc, param); pthread_mutex_lock(&m_mutex); for (j = i; j < nSock - 1;j++) { sock_array[j] = sock_array[j + 1]; } nSock--; pthread_mutex_unlock(&m_mutex); } } } else { cout<<"接收超时!"<<endl; break; } } return ((void *)0); } void socket_server::my_err(const char*err_string, char *function, int line) { fprintf(stderr, "func[%s]line:%d\n", function, line); perror(err_string); exit(1); } void socket_server::socket_op() { pthread_t pid; pthread_create(&pid, NULL, sock_thread_proc, this); int sock_fd; int new_sockfd; struct sockaddr_in serv_addr; struct sockaddr_in client_addr; int nRet; int i; sock_fd = socket(AF_INET, SOCK_STREAM, 0); if (sock_fd < 0) my_err("socket", __FUNCTION__, __LINE__); fcntl(sock_fd, F_SETFL, O_NONBLOCK); //设置socket非阻塞 int optval = 1; //可以重新绑定端口 if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (void *)&optval, sizeof(int)) < 0) my_err("setsockopt", __FUNCTION__, __LINE__); memset(&serv_addr, 0, sizeof(struct sockaddr_in)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(4507); serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); nRet = bind(sock_fd, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr_in)); if (nRet < 0) my_err("bind", __FUNCTION__, __LINE__); nRet = listen(sock_fd, 10000); if (nRet < 0) my_err("listen", __FUNCTION__, __LINE__); int timeout = 5*1000; struct pollfd p_fds; socklen_t addr_len = sizeof(struct sockaddr_in); memset(&p_fds, 0, sizeof(p_fds)); p_fds.fd = sock_fd; p_fds.events = POLLIN; while(1) { nRet = poll((struct pollfd*)&p_fds, 1, timeout); if(nRet > 0) { if (p_fds.revents & POLLIN) { new_sockfd = accept(sock_fd, (struct sockaddr*)&client_addr, &addr_len); pthread_mutex_lock(&m_mutex); sock_array[nSock++] = new_sockfd; //入数组 pthread_cond_signal(&c_lock); pthread_mutex_unlock(&m_mutex); } } else if(nRet == 0) { cout<<"waiting for connecting......"<<endl; continue; } else { cout<<"poll error!"<<endl; } } close(sock_fd); } int main() { socket_server *obj = new socket_server(); cout<<"******socket server begin to accept client******"<<endl; obj->socket_op(); delete obj; return 0; }pool客户端:
#ifndef _SOCKET_CLIENT_H_ #define _SOCKET_CLIENT_H_ #include <iostream> #include <errno.h> #include <stdio.h> #include <stdlib.h> using namespace std; class socket_client { public: socket_client(); virtual ~socket_client(); void socket_connect(const int conn_timeout); private: void my_err(const char*err_string, char *function, int line); }; #endifsocket_client.cpp:
#include "socket_client.h" #include <pthread.h> #include <sys/time.h> #include <sys/select.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <fcntl.h> #include <arpa/inet.h> #include <poll.h> socket_client::socket_client() { } socket_client::~socket_client() { } void socket_client::my_err(const char*err_string, char *function, int line) { fprintf(stderr, "func[%s]line:%d\n", function, line); perror(err_string); exit(1); } void socket_client::socket_connect(const int conn_timeout) { int sock_fd; int nRet; struct sockaddr_in addr; fd_set rdset; fd_set wtset; int retval; char sndbuff[81920] = {0}; FILE *fp = fopen("./file.txt", "r+"); fseek(fp, 0, SEEK_END); int len = ftell(fp); fseek(fp, 0, SEEK_SET); fread(sndbuff, 1, len, fp); //cout<<len<<":"<<strlen(sndbuff)<<endl; char recv_buf[81920] = {0}; sock_fd = socket(AF_INET, SOCK_STREAM, 0); if (sock_fd < 0) my_err("socket", __FUNCTION__, __LINE__); //int nRecvBuf = 32 * 1024; //if (setsockopt(sock_fd, SOL_SOCKET, SO_RCVBUF, (const char*)&nRecvBuf, sizeof(int)) < 0) // my_err("setsockopt", __FUNCTION__, __LINE__); addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr("172.168.1.242"); addr.sin_port = htons(4507); nRet = connect(sock_fd, (struct sockaddr*)&addr, sizeof(addr)); if (nRet < 0) { my_err("connect", __FUNCTION__, __LINE__); } if (fcntl(sock_fd, F_SETFL, fcntl(sock_fd, F_GETFL) | O_NONBLOCK) < 0) { my_err("fcntl", __FUNCTION__, __LINE__); } cout<<"sock_fd1:"<<sock_fd<<endl; for (int i = 0; i < 1000; i++){ int timeout = 10*1000; struct pollfd event; int send_count = 0; memset(&event, 0, sizeof(event)); event.fd = sock_fd; event.events = POLLOUT; send_again: retval = poll((struct polled*)&event, 1, timeout); if (retval == 0) { cout<<"send timeout......"<<endl; } else if (retval > 0) { if(event.revents & POLLOUT) { if ((send_count = send(event.fd, sndbuff, strlen(sndbuff), 0)) < 0) my_err("send", __FUNCTION__, __LINE__); cout<<"send succeed:"<<send_count<<endl; if (send_count < len) { len = len - send_count; goto send_again; } } } // while (1) { memset(&event, 0, sizeof(event)); event.fd = sock_fd; event.events = POLLIN; retry: retval = poll((struct polled*)&event, 1, timeout); if (retval == 0) { cout<<"recv timeout......"<<endl; } else if (retval > 0) { if(event.revents & POLLIN) { memset(recv_buf, 0, sizeof(recv_buf)); //cout<<"bein"<<endl; if ((retval = recv(event.fd, recv_buf, sizeof(recv_buf), 0)) < 0) my_err("recv", __FUNCTION__, __LINE__); if (retval == 0) { break; } recv_buf[retval] = '\0'; cout<<"server接受数据:"<<strlen(recv_buf)<<endl; //fwrite(recv_buf, 1, strlen(recv_buf), fd); if(strstr(recv_buf,"Envelope>")==NULL){ //cout<<"server接受数据:"<<strlen(recv_buf)<<":"<<recv_buf<<endl; goto retry; } // cout<<"server接受数据:"<<strlen(recv_buf)<<":"<<recv_buf<<endl; } } //} } close(sock_fd); } int main() { socket_client *obj = new socket_client(); struct timeval *t_start, *t_end; int timeuse; int i; t_start = new timeval(); gettimeofday(t_start, NULL); for(i = 0; i < 1; i++) obj->socket_connect(10); t_end = new timeval(); gettimeofday(t_end, NULL); timeuse = 1000000 * (t_end->tv_sec - t_start->tv_sec ) + t_end->tv_usec - t_start->tv_usec; printf("时间为(ms):%d, %d\n", timeuse,timeuse/1000); delete obj; delete t_start; delete t_end; return 0; }makefile:
CC=g++ CFLAGS=-g -DDEBUG LDFLAGS= LIBS= all: socket_client socket_server socket_client: socket_client.cpp $(CC) -o $@ $(LDFLAGS) socket_client.cpp $(LIBS) socket_server: socket_server.cpp $(CC) -o $@ $(LDFLAGS) socket_server.cpp $(LIBS) clean: rm -rf *.o socket_client socket_server(4)epool非阻塞服务器和客户端
epool服务器:
#include <stdio.h> #include <sys/epoll.h> #include <stdlib.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/resource.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <strings.h> #define MAXBUF 1024 #define MAXEPOLLSIZE 10000 int main(int argc, char *argv[]) { int listener, new_fd, kdpfd, nfds, n, ret, curfds; socklen_t len; struct sockaddr_in my_addr,their_addr; struct epoll_event ev; struct epoll_event pevent[MAXEPOLLSIZE]; struct rlimit rt; rt.rlim_max = rt.rlim_cur = MAXEPOLLSIZE; if (setrlimit(RLIMIT_NOFILE, &rt) == -1) { perror("setrlimit"); exit(1); } else { printf("设置系统资源参数成功!\n"); } if( (listener = socket( PF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } else { printf("socket 创建成功!\n"); } if (fcntl(listener, F_SETFL, fcntl(listener, F_GETFD, 0) | O_NONBLOCK) == -1) { perror("fcntl"); return -1; } my_addr.sin_family = PF_INET; my_addr.sin_port = htons(5000); my_addr.sin_addr.s_addr = INADDR_ANY; if ( bind( listener, (struct sockaddr*)&my_addr, sizeof(struct sockaddr)) == -1 ) { perror("bind"); exit(1); } else { printf("IP 地址和端口绑定成功\n"); } if (listen(listener, 2) == -1) { perror("listen"); exit(1); } else { printf("开启服务成功!\n"); } kdpfd = epoll_create(MAXEPOLLSIZE); len = sizeof(struct sockaddr_in); ev.events = EPOLLIN | EPOLLET; ev.data.fd = listener; if( epoll_ctl(kdpfd, EPOLL_CTL_ADD, listener, &ev) < 0 ) { fprintf( stderr, "epoll set insertion error: fd=%d\n", listener ); return -1; } else { printf("监听 socket 加入 epoll 成功!\n"); } curfds = 1; int timeout = 10*1000; while(1) { /* 等待有事件发生 */ nfds = epoll_wait(kdpfd, pevent, curfds, timeout); if( nfds == -1 ) { perror("epoll_wait"); break; } else if (nfds == 0) { printf("waiting for connecting...\n"); continue; } for (n = 0; n < nfds; n++) { if (pevent[n].data.fd == listener) { new_fd = accept(listener, (struct sockaddr*)&their_addr, &len ); if( new_fd < 0 ) { perror("accept"); continue; } else { printf("有连接来自于: %s:%d, 分配的 socket 为:%d\n", inet_ntoa(their_addr.sin_addr), ntohs(their_addr.sin_port), new_fd); } if (fcntl(new_fd, F_SETFL, fcntl(new_fd, F_GETFD, 0) | O_NONBLOCK) == -1) { perror("fcntl"); return -1; } ev.events = EPOLLIN | EPOLLET; ev.data.fd = new_fd; if(epoll_ctl( kdpfd, EPOLL_CTL_ADD, new_fd, &ev) < 0) { fprintf(stderr, "把 socket '%d' 加入 epoll 失败!%s\n", new_fd, strerror(errno)); return -1; } curfds ++; } else if(pevent[n].events & EPOLLOUT){ char buf[MAXBUF + 1]; int len; bzero(buf, MAXBUF + 1); len = recv(pevent[n].data.fd, buf, MAXBUF, 0); if (len > 0) { printf("%d接收消息成功:'%s',共%d个字节的数据\n", pevent[n].data.fd, buf, len); } else { if (len < 0) printf("消息接收失败!错误代码是%d,错误信息是'%s'/n", errno, strerror(errno)); else printf("recv empty\n"); close(pevent[n].data.fd); continue; } if (len ==0 && errno != 11) { epoll_ctl(kdpfd, EPOLL_CTL_DEL, pevent[n].data.fd,&ev); curfds--; } } } } close(listener); close(kdpfd); return 0; }epoll客户端:
#include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <sys/epoll.h> #include <stdlib.h> #include <sys/types.h> #include <netinet/in.h> #include <string.h> #define MAXEPOLLSIZE 10000 int main() { int sock_fd; struct sockaddr_in addr; struct epoll_event ev; struct epoll_event pevent[MAXEPOLLSIZE]; int nRet; int count = 0; if( (sock_fd = socket( PF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } addr.sin_family = PF_INET; addr.sin_addr.s_addr = inet_addr("127.0.0.1"); addr.sin_port = htons(5000); nRet = connect(sock_fd, (struct sockaddr*)&addr, sizeof(addr)); if (nRet < 0) { perror("connect"); return -1; } if (fcntl(sock_fd, F_SETFL, fcntl(sock_fd, F_GETFD, 0) | O_NONBLOCK) == -1) { perror("fcntl"); return -1; } int kdpfd = epoll_create(MAXEPOLLSIZE); int len = sizeof(struct sockaddr_in); ev.events = EPOLLOUT | EPOLLET; ev.data.fd = sock_fd; if( epoll_ctl(kdpfd, EPOLL_CTL_ADD, sock_fd, &ev) < 0 ) { fprintf( stderr, "epoll set insertion error: fd=%d\n", sock_fd); return -1; } int curfds = 1; int timeout = 10*1000; int nfds; while(1) { nfds = epoll_wait(kdpfd, pevent, curfds, timeout); if( nfds == -1 ) { perror("epoll_wait"); break; } else if (nfds == 0) { printf("waiting for connecting...\n"); continue; } int n; printf("nfds:%d\n", nfds); for (n = 0; n < nfds; n++) { if (pevent[n].evnets & EPOLLIN) { char send_buf[100] = "my name is aoyang"; count = send(pevent[n].data.fd, send_buf, strlen(send_buf), 0); if (count != strlen(send_buf)) { printf("send error!\n"); } printf("count:%d\n", count); epoll_ctl(kdpfd, EPOLL_CTL_DEL, pevent[n].data.fd,&ev); curfds--; close(pevent[n].data.fd); return 0; } } } }(5)其他设计
#include "user_exception.h" #include "tcpsocket.h" #if defined (MEM_DEBUG) #define new DEBUG_NEW #define delete DEBUG_DELETE #endif namespace util { tcpsocket::tcpsocket() : ipsocket() { _runmode = -1; } tcpsocket::~tcpsocket() { close(); } //client use int tcpsocket::create(const char* ipaddr, int port) { ::memset(&inet_address, 0, sizeof(inet_address)); if (ipaddr == 0) { inet_address.sin_addr.s_addr = htonl(INADDR_ANY); } else { // if (::inet_pton(AF_INET, ipaddr, &inet_address.sin_addr) <= 0) // throw bad_file(__FILE__, __LINE__, bad_file::bad_sock, strerror(errno)); inet_address.sin_addr.s_addr = inet_addr(ipaddr) ; } inet_address.sin_family = AF_INET; inet_address.sin_port = htons(port); _runmode = 0; open(TCP); connect(&inet_address); return 0; } //server use int tcpsocket::create(int port) { open(TCP); ::memset(&inet_address, 0, sizeof(inet_address)); inet_address.sin_family = AF_INET; inet_address.sin_addr.s_addr = htonl(INADDR_ANY); inet_address.sin_port = htons(port); bind(&inet_address); accept(&inet_address); _runmode = 1; return 0; } void tcpsocket::receive(string& msg) { int read_count; int total; int len; char buff[4]; if (this == 0) return; // Read length. total = 0; do { read_count = recv(buff + total, 4 - total); if (read_count < 0) { if (errno == EINTR) continue; else throw bad_file(__FILE__, __LINE__, bad_file::bad_sock, strerror(errno)); } total += read_count; if (total == 0) // No data available. throw bad_file(__FILE__, __LINE__, bad_file::bad_sock, strerror(errno)); } while (total < 4); // Get message length. len = ((buff[0] & 0xff) << 24) + ((buff[1] & 0xff) << 16) + ((buff[2] & 0xff) << 8) + (buff[3] & 0xff); if (len <= 0) throw bad_file(__FILE__, __LINE__, bad_file::bad_sock, strerror(errno)); // Read message. char* data = new char[len + 1]; total = 0; do { read_count = ipsocket::recv(data + total, len - total); if (read_count < 0) { if (errno == EINTR) { continue; } else { delete[] data; throw bad_file(__FILE__, __LINE__, bad_file::bad_sock, strerror(errno)); } } total += read_count; } while (total < len); data[len] = '\0'; msg = data; delete[] data; #if defined(DEBUG) std::cout << "length = " << msg.length() << " [" << msg << "]" << std::endl; #endif } void tcpsocket::send(const string& msg) { #if defined(DEBUG) std::cout << "length = " << msg.length() << " [" << msg << "]" << std::endl; #endif if (this == 0) return; int write_count; int len = msg.length(); char* data = new char[len + 4]; // This is length of packet. data[3] = len & 0xff; data[2] = (len >> 8) & 0xff; data[1] = (len >> 16) & 0xff; data[0] = (len >> 24) & 0xff; memcpy(data + 4, msg.c_str(), len); int total = 0; len += 4; do { write_count = ipsocket::send(data + total, len - total); if (write_count < 0) { if (errno == EINTR) { continue; } else { delete[] data; throw bad_file(__FILE__, __LINE__, bad_file::bad_sock, strerror(errno)); } } total += write_count; } while (total < len); delete[] data ; } }
(1)socket服务器和客户端的代码还可以不断的优化改进以求提高性能和效率。
(2)若有建议,请留言,在此先感谢!