运维最新Handler消息机制(一):Linux的epoll机制(2),2024京东最新Linux运维面试真题解析

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以点击这里获取!

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

#include <unistd.h>

#include <errno.h>

#include <sys/socket.h>

#include <netdb.h>

#include <fcntl.h>

#include <sys/epoll.h>

#include <string.h>

#define MAXEVENTS 64

//函数:

//功能:创建和绑定一个TCP socket

//参数:端口

//返回值:创建的socket

static int

create_and_bind (char *port)

{

struct addrinfo hints;

struct addrinfo *result, *rp;

int s, sfd;

memset (&hints, 0, sizeof (struct addrinfo));

hints.ai_family = AF_UNSPEC; /* Return IPv4 and IPv6 choices */

hints.ai_socktype = SOCK_STREAM; /* We want a TCP socket */

hints.ai_flags = AI_PASSIVE; /* All interfaces */

s = getaddrinfo (NULL, port, &hints, &result);

if (s != 0)

{

fprintf (stderr, “getaddrinfo: %s\n”, gai_strerror (s));

return -1;

}

for (rp = result; rp != NULL; rp = rp->ai_next)

{

sfd = socket (rp->ai_family, rp->ai_socktype, rp->ai_protocol);

if (sfd == -1)

continue;

s = bind (sfd, rp->ai_addr, rp->ai_addrlen);

if (s == 0)

{

/* We managed to bind successfully! */

break;

}

close (sfd);

}

if (rp == NULL)

{

fprintf (stderr, “Could not bind\n”);

return -1;

}

freeaddrinfo (result);

return sfd;

}

//函数

//功能:设置socket为非阻塞的

static int

make_socket_non_blocking (int sfd)

{

int flags, s;

//得到文件状态标志

flags = fcntl (sfd, F_GETFL, 0);

if (flags == -1)

{

perror (“fcntl”);

return -1;

}

//设置文件状态标志

flags |= O_NONBLOCK;

s = fcntl (sfd, F_SETFL, flags);

if (s == -1)

{

perror (“fcntl”);

return -1;

}

return 0;

}

//端口由参数argv[1]指定

int

main (int argc, char *argv[])

{

int sfd, s;

int efd;

struct epoll_event event;

struct epoll_event *events;

if (argc != 2)

{

fprintf (stderr, “Usage: %s [port]\n”, argv[0]);

exit (EXIT_FAILURE);

}

sfd = create_and_bind (argv[1]);

if (sfd == -1)

abort ();

s = make_socket_non_blocking (sfd);

if (s == -1)

abort ();

s = listen (sfd, SOMAXCONN);

if (s == -1)

{

perror (“listen”);

abort ();

}

//除了参数size被忽略外,此函数和epoll_create完全相同

efd = epoll_create1 (0);

if (efd == -1)

{

perror (“epoll_create”);

abort ();

}

event.data.fd = sfd;

event.events = EPOLLIN | EPOLLET;//读入,边缘触发方式

s = epoll_ctl (efd, EPOLL_CTL_ADD, sfd, &event);

if (s == -1)

{

perror (“epoll_ctl”);

abort ();

}

/* Buffer where events are returned */

events = calloc (MAXEVENTS, sizeof event);

/* The event loop */

while (1)

{

int n, i;

n = epoll_wait (efd, events, MAXEVENTS, -1);

for (i = 0; i < n; i++)

{

if ((events[i].events & EPOLLERR) ||

(events[i].events & EPOLLHUP) ||

(!(events[i].events & EPOLLIN)))

{

/* An error has occured on this fd, or the socket is not

ready for reading (why were we notified then?) */

fprintf (stderr, “epoll error\n”);

close (events[i].data.fd);

continue;

}

else if (sfd == events[i].data.fd)

{

/* We have a notification on the listening socket, which

means one or more incoming connections. */

while (1)

{

struct sockaddr in_addr;

socklen_t in_len;

int infd;

char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];

in_len = sizeof in_addr;

infd = accept (sfd, &in_addr, &in_len);

if (infd == -1)

{

if ((errno == EAGAIN) ||

(errno == EWOULDBLOCK))

{

/* We have processed all incoming

connections. */

break;

}

else

{

perror (“accept”);

break;

}

}

//将地址转化为主机名或者服务名

s = getnameinfo (&in_addr, in_len,

hbuf, sizeof hbuf,

sbuf, sizeof sbuf,

NI_NUMERICHOST | NI_NUMERICSERV);//flag参数:以数字名返回

//主机地址和服务地址

if (s == 0)

{

printf("Accepted connection on descriptor %d "

“(host=%s, port=%s)\n”, infd, hbuf, sbuf);

}

/* Make the incoming socket non-blocking and add it to the

list of fds to monitor. */

s = make_socket_non_blocking (infd);

if (s == -1)

abort ();

event.data.fd = infd;

event.events = EPOLLIN | EPOLLET;

s = epoll_ctl (efd, EPOLL_CTL_ADD, infd, &event);

if (s == -1)

{

perror (“epoll_ctl”);

abort ();

}

}

continue;

}

else

{

/* We have data on the fd waiting to be read. Read and

display it. We must read whatever data is available

completely, as we are running in edge-triggered mode

and won’t get a notification again for the same

data. */

int done = 0;

while (1)

{

ssize_t count;

char buf[512];

count = read (events[i].data.fd, buf, sizeof(buf));

if (count == -1)

{

/* If errno == EAGAIN, that means we have read all

data. So go back to the main loop. */

if (errno != EAGAIN)

{

perror (“read”);

done = 1;

}

break;

}

else if (count == 0)

{

/* End of file. The remote has closed the

connection. */

done = 1;

break;

}

/* Write the buffer to standard output */

s = write (1, buf, count);

if (s == -1)

{

perror (“write”);

abort ();

}

}

if (done)

{

printf (“Closed connection on descriptor %d\n”,

events[i].data.fd);

/* Closing the descriptor will make epoll remove it

from the set of descriptors which are monitored. */

close (events[i].data.fd);

}

}

}

}

free (events);

close (sfd);

return EXIT_SUCCESS;

}

代码编译后,./epollTest 8888 ,在另外一个终端中执行

telnet 192.168.1.161 8888 ,192.168.1.161为执行测试程序的ip。在telnet终端敲入任何字符敲入Enter后,会在测试终端显示敲入的字符

总结

=====================================================================

最后的话

最近很多小伙伴找我要Linux学习资料,于是我翻箱倒柜,整理了一些优质资源,涵盖视频、电子书、PPT等共享给大家!

资料预览

给大家整理的视频资料:

给大家整理的电子书资料:

如果本文对你有帮助,欢迎点赞、收藏、转发给朋友,让我有持续创作的动力!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以点击这里获取!

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

总结

=====================================================================

最后的话

最近很多小伙伴找我要Linux学习资料,于是我翻箱倒柜,整理了一些优质资源,涵盖视频、电子书、PPT等共享给大家!

资料预览

给大家整理的视频资料:

[外链图片转存中…(img-YelgNAfz-1715132711843)]

给大家整理的电子书资料:

[外链图片转存中…(img-JIbUk0Qm-1715132711843)]

如果本文对你有帮助,欢迎点赞、收藏、转发给朋友,让我有持续创作的动力!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以点击这里获取!

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 19
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值