版权声明:本文为博主原创文章,未经博主允许不得转载。 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相同)。
结果: