linux下c/c++实例之socket服务器实例

一、简介

二、详解

简单socket服务器和客户端(基础)

服务器:

/*
*   socket简单编程 服务端
 */
 
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
 
#define BUFFSIZE 1024
 
int main(int argc,char *argv[])
{
    int server_sockfd = 0;
    int client_sockfd = 0;
    int len = 0;
    int sin_size = 0;
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    char buf[BUFFSIZE] = {0};
 
    bzero(&server_addr,sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(8000);
 
    if((server_sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0)
    {
        perror("socket error!\n");
        return -1;
    }
 
    if(bind(server_sockfd,(struct sockaddr *)&server_addr,sizeof(struct sockaddr)) < 0)
    {
        perror("bind error!\n");
        return -1;
    }
 
    if(listen(server_sockfd,5) < 0)
    {
        perror("listen error!\n");
        return -1;
    }
 
    sin_size= sizeof(struct sockaddr_in);
 
    if((client_sockfd = accept(server_sockfd,(struct sockaddr *)&client_addr,&sin_size)) < 0)
    {
        perror("accept error!\n");
        return -1;
    }
 
    printf("accept client %s\n",inet_ntoa(client_addr.sin_addr));
    len = send(client_sockfd,"Hello word!\n",30,0);
 
    while((len = recv(client_sockfd,buf,BUFFSIZE,0)) >0)
    {
        buf[len] = '\0';
        printf("buf = %s\n",buf);
        if(send(client_sockfd,len,0) < 0)
        {
            perror("send error!\n");
            return -1;
        }
    }
 
    close(client_sockfd);
    close(server_sockfd);
 
    return 0;
}

 客户端:

/*
*   socket简单编程 客户端
 */
 
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
 
#define BUFFSIZE 1024
 
int main(int argc,char *argv[])
{
    int client_sockfd = 0;
    int len = 0;
    struct sockaddr_in server_addr;
    char buf[BUFFSIZE] = {0};
    bzero(&server_addr,sizeof(struct sockaddr_in));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    server_addr.sin_port = htons(8000);
 
    if((client_sockfd = socket(AF_INET,0)) < 0)
    {
        perror("socket error!\n");
        return -1;
    }
 
    if(connect(client_sockfd,(struct sockaddr*)&server_addr,sizeof(struct sockaddr)) < 0)
    {
        perror("client error!\n");
        return -1;
    }
 
    printf("connect success!\n");
 
    len = recv(client_sockfd,0);
    buf[len] = '\0';
    printf("client_buf = %s\n",buf);
 
    while(1)
    {
        printf("Enter string to send:");
        scanf("%s",buf);
        if(!strcmp(buf,"quit"))
        {
            break;
        }
 
        len = send(client_sockfd,strlen(buf),0);
        len = recv(client_sockfd,0);
        buf[len] = '\0';
        printf("received: %s\n",buf);
    }
 
    close(client_sockfd);
 
    return 0;
}

(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,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,0)) {
        recvbuf[num] = '\0';
        printf("Received client( %s ) message: %s",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,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,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,0);
	if (m_nSocket < 0)
	{
		cout<<"Create Failed!"<<endl;
		return 1;
	}
	cout<<"socket succed!"<<endl;
  fcntl(m_nSocket,O_NONBLOCK);  //设置socket非阻塞
	int nTmp = 1;
    int nRet =setsockopt(m_nSocket,&nTmp,sizeof(int));
    if (nRet < 0)
	{
		return 1;
	}
    cout<<"fcntl succed!"<<endl;
	// 设置SOCKET接收地址和端口
	memset (&m_stSockaddr,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,&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",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;
};
#endif

socket_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,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,&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,&writefds,&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",__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,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,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,0);
    if (sock_fd < 0)
        my_err("socket",__LINE__);
    
    fcntl(sock_fd,O_NONBLOCK); //设置socket非阻塞
    
    int optval = 1;
    //可以重新绑定端口
    if (setsockopt(sock_fd,(void *)&optval,sizeof(int)) < 0)
        my_err("setsockopt",__LINE__);
    memset(&serv_addr,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",__LINE__);
    
    nRet = listen(sock_fd,10000);
    if (nRet < 0)
        my_err("listen",__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,&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客户端:
socket_client.h(头文件):

#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,int line);
    
};
 
#endif

socket_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,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,__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,fcntl(sock_fd,F_GETFL) | O_NONBLOCK) < 0) {
        my_err("fcntl",__LINE__);
    }
    
    nRet = connect(sock_fd,sizeof(addr));
    if (nRet < 0) {
        my_err("fcntl",__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,&wtset,&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",__LINE__);
            cout<<"send succeed!"<<endl;
        }   
    }	
    FD_ZERO(&rdset);
    FD_SET(sock_fd,&rdset);
    retval = select(sock_fd + 1,&rdset,&tv);
    if (retval == 0) {
        cout<<"recv timeout......"<<endl;
    }
    else if (retval > 0) {
        if(FD_ISSET (sock_fd,&rdset)) {
            if ((retval = recv(sock_fd,0)) < 0)
                my_err("recv",__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非阻塞服务器和客户端
pool服务器:
socket_server.h(头文件):

#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,int line);
 
    int sock_array[10000];
    int nSock;
    int maxfd;
    struct pollfd fds[10000];
};
#endif

socket_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,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,SEEK_END);
	int len = ftell(fp);
	fseek(fp,SEEK_SET);
	fread(sndbuff,1,fp);
	while(1) {
		struct pollfd event;
	  memset(&event,sizeof(event));
		event.fd = sockfd;
		event.events = POLLIN;
  recv_continue:
		nRet = poll((struct pollfd*)&event,timeout);
		if (nRet < 0) {
	    printf("poll error!\n");
	    exit(1);	  
		}
		else if (nRet > 0){     //有事件发生
			if (event.revents & POLLIN) {
			  if ((ret = recv(event.fd,0)) < 0)
		      my_err("recv",__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,sizeof(event));
	    event.fd = sockfd;
	    event.events = POLLOUT;
	  send_continue:
	    nRet = poll((struct pollfd*)&event,timeout);
	    if (nRet > 0) {
		    if (event.revents & POLLOUT) {
				  if ((count = send(event.fd,0)) < 0){
					  my_err("send",__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,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,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,int line)
{
	fprintf(stderr,line);
	perror(err_string);
	exit(1);
}
void socket_server::socket_op()
{
	pthread_t pid;
	pthread_create(&pid,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,0);
	if (sock_fd < 0)
		my_err("socket",__LINE__);
		
	fcntl(sock_fd,O_NONBLOCK); //设置socket非阻塞
	
	int optval = 1;
	//可以重新绑定端口
	if (setsockopt(sock_fd,sizeof(int)) < 0)
		my_err("setsockopt",__LINE__);
	memset(&serv_addr,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,sizeof(struct sockaddr_in));
	if (nRet < 0)
		my_err("bind",__LINE__);
		
	nRet = listen(sock_fd,10000);
	if (nRet < 0)
		my_err("listen",__LINE__);
	
	int timeout = 5*1000;
	struct pollfd p_fds;
	socklen_t addr_len = sizeof(struct sockaddr_in);
	memset(&p_fds,sizeof(p_fds));
	p_fds.fd = sock_fd;
	p_fds.events = POLLIN;
	while(1) {
		
		nRet = poll((struct pollfd*)&p_fds,timeout);
		if(nRet > 0) {
			if (p_fds.revents & POLLIN) {
			  new_sockfd = accept(sock_fd,&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客户端:
socket_client.h(头文件):

#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,int line);
    
};
 
#endif

socket_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,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",fp);
	//cout<<len<<":"<<strlen(sndbuff)<<endl;
	
	char recv_buf[81920] = {0};
	sock_fd = socket(AF_INET,__LINE__);
	//int nRecvBuf = 32 * 1024;
	//if (setsockopt(sock_fd,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int)) < 0)
	//	my_err("setsockopt",__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,sizeof(addr));
  if (nRet < 0) {
    my_err("connect",__LINE__);
  }
  if (fcntl(sock_fd,F_GETFL) | O_NONBLOCK) < 0) {
    my_err("fcntl",__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,sizeof(event));
	  event.fd = sock_fd;
	  event.events = POLLOUT;
	send_again:
		retval = poll((struct polled*)&event,timeout);
		if (retval == 0) {
		   cout<<"send timeout......"<<endl;
		}
	  else if (retval > 0) {
	    if(event.revents & POLLOUT) {
	      if ((send_count = send(event.fd,0)) < 0)
	        my_err("send",__LINE__);
	      cout<<"send succeed:"<<send_count<<endl;
	      if (send_count < len) {
	        len = len - send_count;
	        goto send_again;
	      } 
	    }
	  }	
	 // while (1) {
	  memset(&event,sizeof(event));
	  event.fd = sock_fd;
	  event.events = POLLIN;
retry:	  
	  retval = poll((struct polled*)&event,timeout);
	  if (retval == 0) {
		   cout<<"recv timeout......"<<endl;
		}
	  else if (retval > 0) {
	    if(event.revents & POLLIN) {
	    	memset(recv_buf,sizeof(recv_buf));
	    	//cout<<"bein"<<endl;
	      if ((retval = recv(event.fd,0)) < 0)
	    	  my_err("recv",__LINE__);
	    	if (retval == 0) {
	    		break;
	    	}  
	      recv_buf[retval] = '\0';
	      cout<<"server接受数据:"<<strlen(recv_buf)<<endl;
	      //fwrite(recv_buf,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( AF_INET,0)) == -1) {
                perror("socket");
                exit(1);
        }
        else {
                 printf("socket 创建成功!\n");
        }
  if (fcntl(listener,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,fcntl(new_fd,0) | O_NONBLOCK) == -1)
              {
                      perror("fcntl");
                      return -1;
              }
              ev.events = EPOLLIN | EPOLLET;
                                ev.data.fd = new_fd;
                                if(epoll_ctl( kdpfd,&ev) < 0) {
                                  fprintf(stderr,"把 socket '%d' 加入 epoll 失败!%s\n",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,MAXBUF,0);
                                if (len > 0)
                                {
                                        printf("%d接收消息成功:'%s',共%d个字节的数据\n",pevent[n].data.fd,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,&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,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,sizeof(addr));
  if (nRet < 0) {
    perror("connect");
    return -1;
  }
  if (fcntl(sock_fd,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,sock_fd,sock_fd);
                return -1;
        }
        int curfds = 1;
        int timeout = 10*1000;
        int nfds;
        while(1) {
          nfds = epoll_wait(kdpfd,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,&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,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,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__,strerror(errno));
        }
        total += read_count;
        if (total == 0) // No data available.
            throw bad_file(__FILE__,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__,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__,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__,strerror(errno));
            }
        }
        total += write_count;
    } while (total < len);
    delete[] data ;
}
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐