服务器示例
这里使用epoll_data联合体中的ptr指针。
fd的使用链接:epoll_data.fd
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#define MAX_SIZE 5
typedef struct client_info
{
int fd;
struct in_addr addr;
int port;
}client_info;
int main(int argc, char *argv[])
{
int server_fd;
int ret;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
int client_fd;
server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd < 0){
perror("socket error");
return -1;
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(9000);
server_addr.sin_addr.s_addr = inet_addr("192.168.121.128");
int len = sizeof(struct sockaddr_in);
ret = bind(server_fd, (struct sockaddr*)&server_addr, len);
if (ret == -1){
perror("bind error");
return -1;
}
ret = listen(server_fd, MAX_SIZE);
if (ret < 0){
perror("listen error");
return -1;
}
int epoll_fd, nfds = 0, i = 0;
struct epoll_event ev, evs[MAX_SIZE];
//创建一个epoll监听集合
epoll_fd = epoll_create(MAX_SIZE);
client_info *pci = NULL;
pci = (client_info*)malloc(sizeof(client_info));
pci->fd = server_fd;
memcpy(&pci->addr, &server_addr.sin_addr, sizeof(struct in_addr));
pci->port = 0;
ev.events = EPOLLIN | EPOLLET;
ev.data.ptr = pci;
//将监听socket描述符与定义好的事件添加到epoll监听集合中
if ((epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_fd, &ev)) < 0){
perror("epoll_ctl add error");
return -1;
}
for (i = 0;i<MAX_SIZE;i++){
evs[i].data.ptr = NULL;
}
char buff[1024] = {0};
while (1){
//epoll阻塞等待事件触发,当某个描述符触发事件,则将触发的事件写入到evs中
//并且返回触发事件的描述符个数nfds
nfds = epoll_wait(epoll_fd, evs, MAX_SIZE, 3000);
if (nfds < 0){
//epoll等待出错
perror("epoll_wait error");
continue;
}else if (nfds == 0){
//3000毫秒内没有任何描述符触发事件
printf("timeout\n");
continue;
}
//循环从evs中取出触发的事件
for (i = 0;i<nfds;i++){
//如果evs[i].data.fd == sockfd,代表客户端请求通道有客户端请求到来
//则接受客户端连接请求
pci = evs[i].data.ptr;
if (pci->fd == server_fd){
client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &len);
if (client_fd < 0){
perror("new client error");
continue;
}
printf("new accept----[%s:%d]\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
pci = (client_info*)malloc(sizeof(client_info));
pci->fd = client_fd;
memcpy(&pci->addr, &client_addr.sin_addr, sizeof(struct in_addr));
pci->port = ntohs(client_addr.sin_port);
ev.events = EPOLLIN | EPOLLET;
ev.data.ptr = pci;
//add event
ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_fd, &ev);
if (ret < 0){
perror("epoll_ctl add error");
}
//EPOLLIN代表可读事件
}else if (evs[i].events & EPOLLIN){
//代表有其他数据传输,则接受数据
memset(buff, 0x00, 1024);
ret = recv(pci->fd, buff, 1024, 0);
if (ret <= 0){
//ret == 0代表对端断开了tcp连接
//ret < 0 出错
//EINTR被信号打断出错
//EAGAIN描述符没有准备好
if (errno == EAGAIN || errno == EINTR){
continue;
}
//除了上面2个错误之外则从监听集合中删除描述符并关闭socket
if ((epoll_ctl(epoll_fd, EPOLL_CTL_DEL, pci->fd, &ev)) < 0){
perror("epoll_ctl del error");
}
close(pci->fd);
}
printf("%s----[%s:%d]\n", buff, inet_ntoa(pci->addr), pci->port);
}
}
}
close(server_fd);
free(pci);
return 0;
}
客户端示例
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
int sockfd;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
int ret;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0){
perror("socket error");
return -1;
}
int KeepAlive=1;
socklen_t KPlen=sizeof(int);
if(setsockopt(sockfd,SOL_SOCKET,SO_KEEPALIVE,(char *)&KeepAlive,KPlen)!=0){
perror("setsockopt error");
return -1;
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(9000);
server_addr.sin_addr.s_addr = inet_addr("192.168.121.128");
client_addr.sin_family = AF_INET;
client_addr.sin_port = htons(8000);
client_addr.sin_addr.s_addr = inet_addr("192.168.121.128");
int len = sizeof(struct sockaddr_in);
ret = bind(sockfd, (struct sockaddr*)&client_addr, len);
if (ret == -1){
perror("bind error");
return -1;
}
ret = connect(sockfd, (struct sockaddr*)&server_addr, len);
if (ret < 0){
perror("connect error");
return -1;
}
char buff[1024] = {0};
int i = 0;
while (1){
memset(buff, 0x00, 1024);
sprintf(buff, "test1");
send(sockfd, buff, 1024, 0);
sleep(1);
}
close(sockfd);
return 0;
}