- 论坛徽章:
- 0
|
本帖最后由 hsdrhsdr 于 2013-11-01 14:36 编辑
使用epoll了模型,socket设置了keepalive,但为什么时间到了,没能捕获到关闭连接呢,代码如下:
//
// Server.c
// carsoulCloudDogServer
//
// Created by Leo.Chen on 13-8-5.
// Copyright (c) 2013年 carsoul. All rights reserved.
//
#include <stdio.h>
#include <stdio.h>
#include <string.h>
#include <sys/epoll.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include <fcntl.h>
#include "Server.h"
#define MAX_EVENTS 640
static int listen_sock = 0;
static unsigned long int times = 0;
static Server_event_handle *serverCfg = NULL;
//创建并绑定端口
int create_and_bind(int port)
{
int listenfd;
struct sockaddr_in local;
//创建listen socket
if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("create sockfd error");
return -1;
}
memset(&local, 0, sizeof(local));
local.sin_family = AF_INET;
local.sin_addr.s_addr = htonl(INADDR_ANY);;
local.sin_port = htons(port);
if (bind(listenfd, (struct sockaddr *) &local, sizeof(local)) < 0) {
perror("Could not bind:");
return -1;
}
return listenfd;
}
//设置socket为非阻塞
int setnonblocking(int sockfd)
{
int opts;
opts = fcntl(sockfd, F_GETFL);
if(opts < 0) {
perror("fcntl(F_GETFL)\n");
return -1;
}
opts = (opts | O_NONBLOCK);
if(fcntl(sockfd, F_SETFL, opts) < 0) {
perror("fcntl(F_SETFL)\n");
return -1;
}
return 0;
}
int _set_socket_keepalive(int listenfd)
{
int optval;
socklen_t optlen = sizeof(optval);
/* Check the status for the keepalive option */
if(getsockopt(listenfd, SOL_SOCKET, SO_KEEPALIVE, &optval, &optlen) < 0) {
perror("getsockopt()");
close(listenfd);
//exit(EXIT_FAILURE);
}
printf("SO_KEEPALIVE is %s\n", (optval ? "ON" : "OFF"));
/* Set the option active */
optval = 1;
optlen = sizeof(optval);
if(setsockopt(listenfd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) < 0) {
perror("setsockopt()");
close(listenfd);
//exit(EXIT_FAILURE);
}
int keepIdle = 30; //30秒没有数据上来,则发送探测包
int keepInterval = 10; //每隔10发数一个探测包
int keepCount = 3; //发送3个探测包,未收到反馈则主动断开连接
setsockopt(listenfd, SOL_SOCKET, TCP_KEEPIDLE, (void *)&keepIdle, sizeof(keepIdle));
setsockopt(listenfd, SOL_SOCKET,TCP_KEEPINTVL, (void *)&keepInterval, sizeof(keepInterval));
setsockopt(listenfd, SOL_SOCKET, TCP_KEEPCNT, (void *)&keepCount, sizeof(keepCount));
printf("SO_KEEPALIVE set on socket\n");
/* Check the status again */
if(getsockopt(listenfd, SOL_SOCKET, SO_KEEPALIVE, &optval, &optlen) < 0) {
perror("getsockopt()");
close(listenfd);
//exit(EXIT_FAILURE);
}
printf("SO_KEEPALIVE is %s\n", (optval ? "ON" : "OFF"));
}
int server_init(Server_event_handle *server)
{
serverCfg = server;
if ((listen_sock = create_and_bind(serverCfg->port)) == -1) {
return -1;
};
setnonblocking(listen_sock);
//_set_socket_keepalive(listen_sock);
if ((listen(listen_sock, SOMAXCONN)) == -1) {
return -1;
}
return 0;
}
int server_start()
{
char buf[BUFSIZ];
int conn_sock, epollfd, nfds,n, nread;
struct epoll_event ev, events[MAX_EVENTS];
if ((epollfd = epoll_create1(0)) == -1) {
perror("epoll_create");
return -1;
}
ev.events = EPOLLIN;
ev.data.fd = listen_sock;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, listen_sock, &ev) == -1) {
perror("epoll_ctl: listen_sock");
return -1;
}
while (1) {
nfds = epoll_wait(epollfd, events, MAX_EVENTS, 5000);
if (nfds == -1) {
perror("epoll_pwait");
return -1;
}
for (n = 0; n < nfds; ++n) {
//处理其他事件类型
printf("event:%X\n",events[n].events);
if ((events[n].events & EPOLLERR) || (events[n].events & EPOLLHUP)|| (!(events[n].events & EPOLLIN))) {
printf("Closed connection %d\n",events[n].data.fd);
//serverCfg->close_handle(events[n].data.fd);
close(events[n].data.fd);
continue;
}
//处理新连接
if (events[n].data.fd == listen_sock) {
struct sockaddr remote;
socklen_t addrlen;
addrlen = sizeof remote;
char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
conn_sock = accept(listen_sock, (struct sockaddr *) &remote, &addrlen);
if (conn_sock == -1) {
if ((errno == EAGAIN) || (errno== EWOULDBLOCK)) {
break;
} else {
perror("accept");
break;
}
}
if (getnameinfo(&remote,addrlen, hbuf,sizeof hbuf, sbuf,sizeof sbuf,
NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
printf("Accepted connection from %s:%s\n",hbuf,sbuf);
}
if (setnonblocking(conn_sock) == -1) {
break;
}
_set_socket_keepalive(conn_sock);
//为新的连接注册epoll事件
ev.events = EPOLLIN;
ev.data.fd = conn_sock;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock, &ev) == -1) {
perror("epoll_ctl: conn_sock");
return -1;
}
serverCfg->accept_handle(conn_sock);
continue;
}
//处理接收数据
if (events[n].events & EPOLLIN) {
int done = 0;
int code = 0;
while(1) {
code = serverCfg->process_handle(events[n].data.fd);
if ( code == 1) {
done = 1;
break;
} else if (code == 2) {
break;
}
}
if (done) {
printf("Closed connection %d\n",events[n].data.fd);
//serverCfg->close_handle(events[n].data.fd);
close(events[n].data.fd);
}
}
}
}
return 0;
} |
|