Linux C语言网络编程epoll多客户端,服务器转发

下面是server代码:

服务器主要负责等待客服端连接,处理数据,转发!随便瞎写的,主要是为了学习epoll多路复用,有逻辑错误的地方。

#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <netinet/in.h>
#include <errno.h>
#include <sys/epoll.h>
#include <semaphore.h>

#define  OPEN_MAX 20


typedef struct {
	int client_fd;
	char client_name[128];
	struct sockaddr_in client_addr;

}client;
static client *clients = NULL;
static sem_t send_sem;
char from[32] = {0};
char to[32] = {0};
char msg[128] = {0};
char recv_buf[1024] = {0};
struct epoll_event event; 
struct epoll_event wait_event;
int server_fd = -1,target_fd = -1,epfd = -1;
static int retVal = -1;
static int sin_size = 0;
struct sockaddr_in server_addr;
struct sockaddr_in new_client_addr;
pthread_t send_thread_id;
pthread_t recv_thread_id;

/*
 *
 *
 * test 
 *
 *
 * */

static void showAllClients(void)
{
	int i;
	for(i = 0; i < OPEN_MAX; i++){
		if(clients[i].client_fd == 0){
			continue;
		}else{
			printf("showAllClients clients[%d]:client_fd = %d :name = %s\n",i,clients[i].client_fd,clients[i].client_name);
		}
	}
}

static int getClientsIndex(int byfd, char * byname)
{
	int i;
	if( byfd > 0 ){
		for(i = 0; i < OPEN_MAX;i++){
			if(clients[i].client_fd == byfd){
				return i;
			}else{
				continue;
			}
		}
	}
	else if ( byname != NULL){
		for(i = 0; i < OPEN_MAX;i++){
			if(strstr(clients[i].client_name,byname)){
				return i;
			}else{
				continue;
			}
		}
	}
	else {
		printf("getClientsIndex error\n");
		return -1;
	}

}

void send_thread(void)
{
	int i = 0;
	while(1){
		sem_wait(&send_sem);
		int index = getClientsIndex(0,to);
		if(index < 0){
			continue;
		}
		printf("index =%d,target_fd =%d\n",index,clients[index].client_fd);
		retVal = write(clients[index].client_fd,msg,strlen(msg));
		printf("send %d bytes success \n",retVal);
		memset(msg,0,128);
		memset(to,0,32);
		memset(from,0,32);
	}
}

/*
MSG:from:xxx,to:xxx,msg:
*/
static int analysisMessage(int fd)
{
	char *p_str,*p_end;
	if(recv_buf[0] == 0){
		printf("recv_buf is invalid\n");
		return -1;
	}

	printf("recv data:%s\n",recv_buf);
	p_str = strstr((recv_buf),"register:");
	if(p_str){
		p_str = p_str+9;
		int index = getClientsIndex(fd,NULL);
		printf("getClientsIndex index = %d\n",index);
		if(index >= 0){
			strcpy(clients[index].client_name,p_str);
			memset(recv_buf,0,sizeof(recv_buf));
			return 0;
		}
		return -1;
	}
	p_str = strstr((recv_buf),"from:");
	if(p_str){
		p_str = p_str+5;
		p_end = strstr(p_str,"to:") - 1;
		strncpy(from,p_str,p_end-p_str);
		printf("from:%s\n",from);
	}else {
		printf("analysisMessage form error p_str is null\n");
		return -1;
	}

	p_str = strstr((recv_buf),"to:");
	if(p_str){
		p_str = p_str+3;
		p_end = strstr(p_str,"msg:") - 1;
		strncpy(to,p_str,p_end-p_str);
		printf("to:%s\n",to);
	}else {
		printf("analysisMessage to error p_str is null\n");
		return -1;
	}
	p_str = strstr((recv_buf),"msg:");
	if(p_str){
		p_str = p_str+4;
		strcpy(msg,p_str);
		printf("msg:%s\n",msg);
	}else {
		printf("analysisMessage msg error p_str is null\n");
		return -1;
	}
	sem_post(&send_sem);
}


int main()
{
	int i = 0,connectCount = 0,j = 0;
	if(sem_init (&send_sem , 0, 0) < 0){
		perror("sem_init:");
		return -1;
	}
	clients = malloc(sizeof(clients)*OPEN_MAX);
	if(clients == NULL){
		printf("malloc clients fail\n");
		return -1;
	}
	printf("malloc clients success\n");
	memset(clients,0, sizeof(clients)*OPEN_MAX);
	memset(&event,0,(sizeof(event)));
    server_fd = socket(AF_INET, SOCK_STREAM,0);
    if(server_fd < 0){
        printf("creat socket fail,error:%s\n",strerror(server_fd));
        return -1;
    }
    printf("creat socket success server_fd = %d !\n",server_fd);
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr("198.18.108.235");/*htonl(INADDR_ANY);*/
    server_addr.sin_port = htons(6000);

    retVal = bind(server_fd,(struct sockaddr *)&server_addr, sizeof(server_addr));
    if(retVal < 0){
        printf("server bind fail,error:%s,retVal = %d\n",strerror(retVal),retVal);
        return -1;
    }
    printf("server bind success ! server ip:%s,port:6000\n",inet_ntoa(server_addr.sin_addr));

    retVal = listen(server_fd,5);
    if(retVal < 0){
        printf("server listen fail,error:%s\n",strerror(retVal));
        return -1;
    }
    printf("server listen success !\n");
	epfd = epoll_create(10); 
	if( -1 == epfd ){    
		perror ("epoll_create");    
		return -1;    
	} 
    printf("epoll_create success  epfd = %d!\n",epfd);
	event.data.fd = server_fd;    
	event.events = EPOLLIN; 
	retVal = epoll_ctl(epfd, EPOLL_CTL_ADD, server_fd, &event);    
	if(-1 == retVal){    
		perror("epoll_ctl add fail");    
		return -1;    
	}
	retVal = pthread_create(&send_thread_id,NULL,(void *) send_thread,NULL);
	if(retVal < 0){ 
		printf("create send thread fail \n");
		return -1; 
	} 
	while(1){

		retVal = epoll_wait(epfd, &wait_event, connectCount+1, -1);
		if((server_fd == wait_event.data.fd) && 
					(EPOLLIN == wait_event.events & EPOLLIN)){

			showAllClients();
			int new_client_fd = accept(server_fd,(struct sockaddr *)&new_client_addr,&sin_size);
			if(new_client_fd < 0){
				printf("server accept fail,error:%s\n",strerror(clients[i].client_fd));
				return -1;
			}
			if(connectCount >= OPEN_MAX){
				close(new_client_fd);
				printf("server refuse new connect\n");
				continue;
			}
			printf("a new accept success ,client fd = %d\n",new_client_fd);
			for(i = 0;i < OPEN_MAX;i++){
				if(clients[i].client_fd == 0){
					clients[i].client_fd = new_client_fd;
					clients[i].client_addr = new_client_addr;
					event.data.fd = new_client_fd; 
					event.events = EPOLLIN;
					printf("+++sjh+++ clients[%d].client_fd = %d\n",i,clients[i].client_fd);
					retVal = epoll_ctl(epfd, EPOLL_CTL_ADD, new_client_fd, &event);    
					if(-1 == retVal){    
						perror("epoll_ctl add fail");    
						return -1;    
					}
					connectCount++;
					break;
				}else {
					continue;
				}
			}

		} else {
			for(j = 0;j < OPEN_MAX;j++){
				if((clients[j].client_fd == wait_event.data.fd) 
							&& (EPOLLIN == wait_event.events & EPOLLIN)){

					retVal = recv(clients[j].client_fd, recv_buf, sizeof(recv_buf), 0);
					if(retVal < 0){   
						if(errno == ECONNRESET)
						{   
							connectCount--;
							close(clients[j].client_fd);  
							memset(&clients[j],0,sizeof(clients));
						}   
						else  
						  perror("read error:");  
					} else if(retVal == 0){   
						printf("client [fd:%d,name:%s] has been closed\n",clients[j].client_fd,clients[j].client_name);
						connectCount--;
						close(clients[j].client_fd);  
						memset(&clients[j],0,sizeof(clients));
					} else {
					  analysisMessage(clients[j].client_fd); 
					}
				}
			}
		}
	}
	/*
    retVal = pthread_create(&recv_thread_id,NULL,(void *) recv_thread,NULL);
    if(retVal < 0){
        printf("create recv thread fail \n");
        return -1;
    }*/
   // pthread_join(recv_thread_id, NULL);
    pthread_join(send_thread_id, NULL);
	return 0;

}

下面是客户端程序:

/*************************************
name: client.c 
linux sockek

  */

#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <linux/in.h>
#include <string.h>
//#include <netinet/in.h>


int client_fd;
int retVal,recBytes;
int sin_size;
struct sockaddr_in s_add,c_add;
unsigned short portnum=6000;

char client_name[128] = {0};
pthread_t send_thread_id;
pthread_t recv_thread_id;
//from:xxx,to:xxx,msg:
void send_thread(void)
{
	char msg[128] = {0};
	char send_buf[128] = {0};

	while(1){
		printf("send data:\n");
		fgets(msg,128,stdin);
		sprintf(send_buf,"from:%s,%s",client_name,msg);
		if(client_fd  != -1){
			retVal = write(client_fd,send_buf,strlen(send_buf));
			printf("send %d bytes success \n",retVal);
		}else {
			printf("client exit !\n");
			break;
		}
		memset(send_buf,0,128);
		memset(msg,0,128);
	}
}


void recv_thread(void)
{
	char recv_buf[128] = {0};
	while(1){
		retVal = read(client_fd,recv_buf,sizeof(recv_buf));
		if(retVal == 0){
			close(client_fd);
			client_fd = -1;
			printf("server has been closed\n press down any key to exit!\n");
			break;
		}
		printf("recv data :%s\n",recv_buf);
		memset(recv_buf,0,128);
	}
}

int main(int argc,char** argv)
{
	char register_cmd[128] = {0};
	if(argc < 2){
		printf("please input parameter !\n");
		return -1;
	}else {
		strcpy(client_name,argv[1]);
		strcpy(register_cmd,"register:");
		strcat(register_cmd,argv[1]);
	}
	
    printf("Hello,welcome to client !\r\n");
    client_fd = socket(AF_INET, SOCK_STREAM, 0);
    if(-1 == client_fd) {
        printf("socket fail ! \r\n");
        return -1;
    }
    printf("socket ok !\r\n");
    bzero(&s_add,sizeof(struct sockaddr_in));
    s_add.sin_family=AF_INET;
    s_add.sin_addr.s_addr= inet_addr("198.18.108.235");
    s_add.sin_port=htons(portnum);
    //printf("s_addr = %s ,port : %d\r\n",inet_ntoa(s_add.sin_addr),s_add.sin_port);

    if(-1 == connect(client_fd,(struct sockaddr *)(&s_add), sizeof(struct sockaddr))) {
        printf("connect fail !\r\n");
		close(client_fd);
        return -1;
	}
	write(client_fd,register_cmd,strlen(register_cmd));
	printf("connect ok !\r\n");
	retVal = pthread_create(&send_thread_id,NULL,(void *) send_thread,NULL);
	if(retVal < 0){ 
		printf("create send thread fail \n");
		close(client_fd);
		return -1; 
	}
    retVal = pthread_create(&recv_thread_id,NULL,(void *) recv_thread,NULL);
	if(retVal < 0){ 
		printf("create recv thread fail \n");
		close(client_fd);
		return -1; 
	} 
	pthread_join(send_thread_id, NULL);
	pthread_join(recv_thread_id, NULL);
	/*
    close(client_fd);*/
    return 0;



}

猜你喜欢

转载自blog.csdn.net/u013255351/article/details/79865127