<span style="font-size:18px;"><span style="font-size:18px;">server.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <errno.h>
#include <sys/epoll.h>
#include <fcntl.h>
#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 8000
#define MAX_RECV_LEN 1024
#define MAX_CLIENT_NUM 30
#define MAX_EVENT MAX_CLIENT_NUM</span>
#define BACK_LOG 20
static int running = 1;
int set_non_block (int fd)
{
int flags, s;
flags = fcntl (fd, F_GETFL, 0);
if (flags == -1)
{
perror ("fcntl");
return -1;
}
flags |= O_NONBLOCK;
s = fcntl (fd, F_SETFL, flags);
if (s == -1)
{
perror ("fcntl");
return -1;
}
return 0;
}
int main (int argc, char *argv[])</span>
{
<span style="white-space:pre"> </span>int sock_fd = -1;
int ret = -1;
struct sockaddr_in serv_addr;
struct sockaddr_in cli_addr;
socklen_t serv_addr_len = 0;
socklen_t cli_addr_len = 0;
char recv_buf[MAX_RECV_LEN];
int new_conn_fd = -1;
int i = 0;
int max_fd = -1;
int num = -1;
int ep_fd = -1;
memset (&serv_addr, 0, sizeof (serv_addr));
memset (&cli_addr, 0, sizeof (cli_addr));
sock_fd = socket (AF_INET, SOCK_STREAM, 0);
if (sock_fd < 0)
{
perror ("Fail to socket");
exit (1);
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons (SERVER_PORT);
serv_addr.sin_addr.s_addr = inet_addr (SERVER_IP);
unsigned int value = 1;
if (setsockopt (sock_fd, SOL_SOCKET, SO_REUSEADDR, (void *) &value, sizeof (value)) < 0)
{
perror ("Fail to setsockopt");
exit (1);
}
serv_addr_len = sizeof (serv_addr);
if (bind (sock_fd, (struct sockaddr *) &serv_addr, serv_addr_len) < 0)
{
perror ("Fail to bind");
exit (1);
}
if (listen (sock_fd, BACK_LOG) < 0)
{
perror ("Fail to listen");
exit (1);
}
set_non_block (sock_fd);//epoll使用边缘触发模式时要将监听的描述符设置成非阻塞
ep_fd = epoll_create (MAX_EVENT);//epoll建立
if (ep_fd < 0)
{
perror ("Fail to epoll_create");
exit (1);
}
struct epoll_event ev, ev_ready[MAX_EVENT];
bzero (&ev, sizeof (ev));
ev.data.fd = sock_fd;
ev.events = EPOLLIN | EPOLLET;
ret = epoll_ctl (ep_fd, EPOLL_CTL_ADD, sock_fd, &ev);//加入监听描述符
if (ret < 0)
{
perror ("Fail to epoll_ctl");
exit (1);
}
char buf[1024];
int len;
int timeout = 5000; //ms
while (running)
{
bzero (&ev_ready, sizeof (ev_ready));
ret = epoll_wait (ep_fd, ev_ready, MAX_EVENT, timeout);
if (ret == 0)
{
printf ("timeout\n");
}
else if (ret < 0)
{
printf ("error occur\n");
}
else
{
for (i = 0; i < ret; i++)
{
if (ev_ready[i].data.fd == sock_fd)
{
printf ("new client comes\n");
len = sizeof (cli_addr);
new_conn_fd = accept (sock_fd, (struct sockaddr *) &cli_addr, &len);
if (new_conn_fd < 0)
{
perror ("Fail to accept");
exit (1);
}
else
{
set_non_block (new_conn_fd);
ev.data.fd = new_conn_fd;
ev.events = EPOLLIN | EPOLLET;
epoll_ctl (ep_fd, EPOLL_CTL_ADD, new_conn_fd, &ev);
}
}
else
{
if (ev_ready[i].events & EPOLLIN)
{
int fd = ev_ready[i].data.fd;
memset (recv_buf, 0, MAX_RECV_LEN);
{
num = read (fd, recv_buf, MAX_RECV_LEN);
if (num < 0)
{
printf ("Client(%d) left\n", fd);
ev.data.fd = fd;
ev.events = EPOLLIN | EPOLLET;
epoll_ctl (ep_fd, EPOLL_CTL_DEL, fd, &ev);
close (fd);
}
else if (num > 0)
{
recv_buf[num] = '\0';
printf ("Recieve client(%d) data\n", fd);
printf ("Data: %s\n\n", recv_buf);
}
if (num == 0)
{
printf ("Client(%d) exit\n", fd);
ev.data.fd = fd;
ev.events = EPOLLIN | EPOLLET;
epoll_ctl (ep_fd, EPOLL_CTL_DEL, fd, &ev);//删除描述符
close (fd);
}
}
}
}
}
}
}
return 0;
}
client.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/select.h>
#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 8000
#define MAX_RECV_LEN 1024
static int running = 1;
int main (int argc, char *argv[])
{
int sock_fd = -1;
int ret = -1;
struct sockaddr_in serv_addr;
struct sockaddr_in cli_addr;
socklen_t serv_addr_len = 0;
memset (&serv_addr, 0, sizeof (serv_addr));
sock_fd = socket (AF_INET, SOCK_STREAM, 0);
if (sock_fd < 0)
{
perror ("Fail to socket");
exit (1);
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons (SERVER_PORT);
serv_addr.sin_addr.s_addr = inet_addr (SERVER_IP);
serv_addr_len = sizeof (serv_addr);
if (connect (sock_fd, (struct sockaddr *) &serv_addr, serv_addr_len) < 0)
{
perror ("Fail to connect");
exit (1);
}
char buf[1024];
int num = 0;
while (running)
{
num = read (STDIN_FILENO, buf, MAX_RECV_LEN);
if (num > 0)
{
buf[num] = '\0';
printf ("buf: %s\n", buf);
num = write (sock_fd, buf, num);
if (num < 0)
{
printf ("write failed\n");
exit (1);
}
if (strncmp (buf, "exit", strlen ("exit")) == 0)
{
printf ("Client exit\n");
close (sock_fd);
return 0;
}
}
}
return 0;
}
Makefile:
all: client server
gcc -o client client.c
gcc -o server server.c
</span></span>
服务端log:
timeout
new client comes
Recieve client(5) data
Data: hello
timeout
new client comes
timeout
Recieve client(6) data
Data: hello
timeout
Client(6) exit
timeout
new client comes
timeout
Client(5) exit
timeout