Linux----IO框架库libevent的使用 (加IO函数的框架库实现服务器客户端通信)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_41026740/article/details/83626870

一、serlib.c程序为加io函数的框架库实现服务器客户端通信【不完善

不完善体现在:多客户端时,一个客户端断开连接后致使服务器也直接断开,中断了其他客户端与服务器的连接通信。

改进版参考以下serlib2.c程序。

服务端serlib.c

#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <signal.h>
#include <unistd.h>
#include <event.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#define MAXFD 20
//加io函数的io框架库实现服务器客户端通信【不完善】
void c_cb(int fd, short ev, void *arg)
{
	if(ev & EV_READ)
	{
		char buff[128] = {0};
		recv(fd, buff, 127, 0);

		printf("buff=%s\n", buff);
		send(fd, "ok", 2, 0);
	}
}

void accept_cb(int fd, short ev, void *arg)
{
	struct sockaddr_in caddr;
	int len = sizeof(caddr);
	if(ev & EV_READ)
	{
		struct event_base *base = (struct event_base*)arg;
		int c = accept(fd,(struct sockaddr *)&caddr, &len);
		if(c < 0)
		{
			return;
		}
		struct event *ev_c = event_new(base,c,EV_READ|EV_PERSIST,c_cb,NULL);
		event_add(ev_c,NULL);
	}
}

int main()
{
	int sockfd = socket(AF_INET, SOCK_STREAM, 0);
	assert(sockfd != -1);

	struct sockaddr_in saddr, caddr;
	memset(&saddr,0,sizeof(saddr));
	saddr.sin_family = AF_INET;
	saddr.sin_port = htons(6000);
	saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
	int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
	assert(res != -1);
	
	listen(sockfd, 5);

	struct event_base *base = event_init();
	assert(base != NULL);

	struct event* ev_sock = event_new(base,sockfd,EV_READ|EV_PERSIST,accept_cb,base);

	event_add(ev_sock,NULL);
	event_base_dispatch(base);
	event_free(ev_sock);
	event_base_free(base);
}

客户端clilib.c

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main()
{
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    assert(sockfd != -1);
    struct sockaddr_in saddr;
    memset(&saddr, 0, sizeof(saddr));
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(6000);
    saddr.sin_addr.s_addr = inet_addr("127.0.0.1");

    int res = connect(sockfd,(struct sockaddr*)&saddr, sizeof(saddr));
    assert(res != -1);

    while(1)
    {
        char buff[128] = {0};
        printf("input:\n");
        fgets(buff,128,stdin);
        if(strncmp(buff,"end",3) == 0)
        {
            break;
            }
        send(sockfd, buff, strlen(buff), 0);
        memset(buff, 0, 128);
        recv(sockfd, buff, 127, 0);
          printf("buff=%s\n",buff);
        }
      close(sockfd);
      exit(0);
    }

结果:

二、以下的serlib2.c为serlib.c的改进版,解决了一个客户端断开连接而使客户端与服务器也断开的bug。

     如下所示,一个客户端断开连接,其他客户端也与服务器正常通信。

服务器端:serlib2.c

#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <signal.h>
#include <unistd.h>
#include <event.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#define MAXFD 20

//加io函数的io框架库实现服务器客户端通信[改进过的]
struct event* fds_map[MAXFD];
void fds_map_init(struct event* fds[])
{
	int i = 0;
	for(; i<MAXFD; i++)
	{
		fds[i] = NULL;
	}
}

void fds_map_add(struct event *fds[],int fd, struct event *ev)
{
	if(fd >= MAXFD || ev == NULL)
	{
		return;
	}
	fds[fd] = ev;
}

struct event* fds_map_find(struct event *fds[], int fd)
{
	return fds[fd];
}

void fds_map_del(struct event *fds[], int fd)
{
	if(fd >= MAXFD)
	{
		return;
	}
	fds[fd] = NULL;
}

void c_cb(int fd, short ev, void *arg)
{
	if(ev & EV_READ)
	{
		char buff[128] = {0};
		if(recv(fd, buff, 127, 0) <= 0)
		{
			event_free(fds_map_find(fds_map,fd));
			fds_map_del(fds_map,fd);
			close(fd);
			printf("one client over\n");
			return;
		}
		printf("buff=%s\n", buff);
		send(fd, "ok", 2, 0);
	}
}

void accept_cb(int fd, short ev, void *arg)
{
	struct sockaddr_in caddr;
	int len = sizeof(caddr);
	if(ev & EV_READ)
	{
		struct event_base *base = (struct event_base*)arg;
		int c = accept(fd,(struct sockaddr *)&caddr, &len);
		if(c < 0)
		{
			return;
		}
		struct event *ev_c = event_new(base,c,EV_READ|EV_PERSIST,c_cb,NULL);
		event_add(ev_c,NULL);

		fds_map_add(fds_map,c,ev_c);
	}
}

int main()
{
	int sockfd = socket(AF_INET, SOCK_STREAM, 0);
	assert(sockfd != -1);

	struct sockaddr_in saddr, caddr;
	memset(&saddr,0,sizeof(saddr));
	saddr.sin_family = AF_INET;
	saddr.sin_port = htons(6000);
	saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
	int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
	assert(res != -1);
	
	listen(sockfd, 5);

	fds_map_init(fds_map);
	struct event_base *base = event_init();
	assert(base != NULL);

	struct event* ev_sock = event_new(base,sockfd,EV_READ|EV_PERSIST,accept_cb,base);
	event_add(ev_sock,NULL);

	fds_map_add(fds_map,sockfd,ev_sock);

	event_base_dispatch(base);
	event_free(ev_sock);
	event_base_free(base);
}

客户端clilib.c同上(与一中的clilib.c相同)。

结果:

猜你喜欢

转载自blog.csdn.net/qq_41026740/article/details/83626870
今日推荐