source: example/io/simple/server_epoll.c@ 361bf01

ADT arm-eh ast-experimental enum forall-pointer-decay jacob/cs343-translation new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since 361bf01 was f0d67e5, checked in by Thierry Delisle <tdelisle@…>, 5 years ago

Restored io examples to example folder

  • Property mode set to 100644
File size: 4.8 KB
RevLine 
[7458fea]1/*
2Similar to the server in servier.c, this is a simple server
3that instead uses epoll to block.
4It opens the door to have several polling user-thread per cluster.
5It uses liburing for simplicity.
6*/
7
8
9#include <assert.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13
14#include <unistd.h>
15
16#include <sys/epoll.h>
17#include <sys/types.h>
18#include <sys/socket.h>
19#include <netinet/in.h>
20
21#include <liburing.h>
22
23#define MAX_EVENTS 10
24struct epoll_event ev, events[MAX_EVENTS];
25
26struct io_uring ring;
27
28char data[256];
29struct iovec iov = { data, 256 };
30struct msghdr msg = { (void *)"", 0, &iov, 1, NULL, 0, 0 };
31static void async_read(int sock) {
32 /* get an sqe and fill in a READ operation */
33 struct io_uring_sqe * sqe = io_uring_get_sqe(&ring);
34 io_uring_prep_recvmsg(sqe, sock, &msg, 0);
35 sqe->user_data = 0;
36
37 /* tell the kernel we have an sqe ready for consumption */
38 int ret = io_uring_submit(&ring);
39 assert(ret == 1);
40}
41
42int main(int argc, char *argv[]) {
43 if(argc != 2) {
44 printf("usage: %s portnumber\n", argv[0]);
45 exit( EXIT_FAILURE );
46 }
47 int port = atoi(argv[1]);
48 if(port < 1) {
49 printf("Invalid port : %d (from %s)\n", port, argv[1]);
50 exit( EXIT_FAILURE );
51 }
52
53 int sock = socket(AF_INET, SOCK_STREAM, 0);
54 if(sock < 0) {
55 perror( "socket" );
56 exit( EXIT_FAILURE );
57 }
58
59 struct sockaddr_in serv_addr;
60 memset(&serv_addr, 0, sizeof(serv_addr));
61 serv_addr.sin_family = AF_INET;
62 serv_addr.sin_addr.s_addr = INADDR_ANY;
63 serv_addr.sin_port = htons(port);
64
65 int ret = bind(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
66 if(ret < 0) {
67 perror( "bind" );
68 exit( EXIT_FAILURE );
69 }
70
71
72 listen(sock,1);
73
74 struct sockaddr_in cli_addr;
75 __socklen_t clilen = sizeof(cli_addr);
76 int newsock = accept(sock, (struct sockaddr *) &cli_addr, &clilen);
77 if (newsock < 0) {
78 perror( "accept" );
79 exit( EXIT_FAILURE );
80 }
81
82 io_uring_queue_init( 16, &ring, 0 );
83
84 int epollfd = epoll_create1(0);
85 if (epollfd == -1) {
86 perror("epoll_create1");
87 exit(EXIT_FAILURE);
88 }
89
90 ev.events = EPOLLIN | EPOLLONESHOT;
91 ev.data.u64 = (uint64_t)&ring;
92 if (epoll_ctl(epollfd, EPOLL_CTL_ADD, ring.ring_fd, &ev) == -1) {
93 perror("epoll_ctl: first");
94 exit(EXIT_FAILURE);
95 }
96
97
98 async_read( newsock );
99
100 while(1) {
101 BLOCK:
102 int nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
103 if (nfds == -1) {
104 perror("epoll_wait");
105 exit(EXIT_FAILURE);
106 }
107
108
109 while(1) {
110 struct io_uring_cqe * cqe;
111 int ret = io_uring_peek_cqe( &ring, &cqe );
112
113 if( ret < 0 ) {
114 if(-ret == EAGAIN) {
115 if (epoll_ctl(epollfd, EPOLL_CTL_MOD, ring.ring_fd, &ev) == -1) {
116 perror("epoll_ctl: loop");
117 exit(EXIT_FAILURE);
118 }
119 goto BLOCK;
120 }
121 printf( "Main Loop Error : %s\n", strerror(-ret) );
122 close( sock );
123 exit( EXIT_FAILURE );
124 }
125
126 switch(cqe->user_data) {
127 // Read completed
128 case 0:
129 // If it is the end of file we are done
130 if( cqe->res == 0 ) {
131 goto END;
132 }
133
134 if( cqe->res < 0 ) {
135 perror( "Main Loop Error" );
136 close( sock );
137 exit( EXIT_FAILURE );
138 }
139
140 printf("'%.*s'\n", cqe->res, data);
141
142 async_read( newsock );
143
144 // otherwise prepare a new read
145 break;
146 // Wait timed out, time to print
147 // Requires Linux 5.4
148 case LIBURING_UDATA_TIMEOUT:
149 printf(".");
150 break;
151 // Problem
152 default:
153 printf("Unexpected user data : %llu", cqe->user_data);
154 exit( EXIT_FAILURE );
155 }
156
157 io_uring_cqe_seen( &ring, cqe );
158 }
159 }
160END:
161
162 io_uring_queue_exit( &ring );
163
164 ret = close(newsock);
165 if(ret < 0) {
166 perror( "close new" );
167 exit( EXIT_FAILURE );
168 }
169
170 ret = close(sock);
171 if(ret < 0) {
172 perror( "close old" );
173 exit( EXIT_FAILURE );
174 }
175
176 return 0;
177}
Note: See TracBrowser for help on using the repository browser.