source: example/io/simple/server.c@ 4740281

Last change on this file since 4740281 was 0640189e, checked in by Thierry Delisle <tdelisle@…>, 4 years ago

Added example of a server using o_NONBLOCK, which does NOT work with io_uring

  • Property mode set to 100644
File size: 3.5 KB
Line 
1/*
2This is a simple server that users io_uring in blocking mode.
3It demonstrates the bare minimum needed to use io_uring.
4It uses liburing for simplicity.
5*/
6
7
8#include <assert.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12
13#include <unistd.h>
14
15#include <sys/types.h>
16#include <sys/socket.h>
17#include <netinet/in.h>
18
19#include <liburing.h>
20
21struct io_uring ring;
22
23char data[256];
24struct iovec iov = { data, 256 };
25struct msghdr msg = { (void *)"", 0, &iov, 1, NULL, 0, 0 };
26static void async_read(int sock) {
27 /* get an sqe and fill in a READ operation */
28 struct io_uring_sqe * sqe = io_uring_get_sqe(&ring);
29 io_uring_prep_recvmsg(sqe, sock, &msg, 0);
30 sqe->user_data = 0;
31
32 /* tell the kernel we have an sqe ready for consumption */
33 int ret = io_uring_submit(&ring);
34 assert(ret == 1);
35}
36
37int main(int argc, char *argv[]) {
38 if(argc != 2) {
39 printf("usage: %s portnumber\n", argv[0]);
40 exit( EXIT_FAILURE );
41 }
42 int port = atoi(argv[1]);
43 if(port < 1) {
44 printf("Invalid port : %d (from %s)\n", port, argv[1]);
45 exit( EXIT_FAILURE );
46 }
47
48 int sock = socket(AF_INET, SOCK_STREAM, 0);
49 if(sock < 0) {
50 perror( "socket" );
51 exit( EXIT_FAILURE );
52 }
53
54 struct sockaddr_in serv_addr;
55 memset(&serv_addr, 0, sizeof(serv_addr));
56 serv_addr.sin_family = AF_INET;
57 serv_addr.sin_addr.s_addr = INADDR_ANY;
58 serv_addr.sin_port = htons(port);
59
60 int ret = bind(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
61 if(ret < 0) {
62 perror( "bind" );
63 exit( EXIT_FAILURE );
64 }
65
66
67 listen(sock,1);
68
69 struct sockaddr_in cli_addr;
70 __socklen_t clilen = sizeof(cli_addr);
71 int newsock = accept(sock, (struct sockaddr *) &cli_addr, &clilen);
72 if (newsock < 0) {
73 perror( "accept" );
74 exit( EXIT_FAILURE );
75 }
76
77 io_uring_queue_init( 16, &ring, 0 );
78
79 async_read( newsock );
80
81 while(1) {
82 struct io_uring_cqe * cqe;
83 struct __kernel_timespec ts = { 2, 0 };
84 // int ret = io_uring_wait_cqes( &ring, &cqe, 1, &ts, NULL); // Requires Linux 5.4
85 int ret = io_uring_wait_cqe( &ring, &cqe );
86
87 if( ret < 0 ) {
88 printf( "Main Loop Error : %s\n", strerror(-ret) );
89 close( sock );
90 exit( EXIT_FAILURE );
91 }
92
93 switch(cqe->user_data) {
94 // Read completed
95 case 0:
96 // If it is the end of file we are done
97 if( cqe->res == 0 ) {
98 goto END;
99 }
100
101 if( cqe->res < 0 ) {
102 perror( "Main Loop Error" );
103 close( sock );
104 exit( EXIT_FAILURE );
105 }
106
107 printf("'%.*s'\n", cqe->res - 1, data);
108
109 async_read( newsock );
110
111 // otherwise prepare a new read
112 break;
113 // Wait timed out, time to print
114 // Requires Linux 5.4
115 case LIBURING_UDATA_TIMEOUT:
116 printf(".");
117 break;
118 // Problem
119 default:
120 printf("Unexpected user data : %llu", cqe->user_data);
121 exit( EXIT_FAILURE );
122 }
123
124 io_uring_cqe_seen( &ring, cqe );
125 }
126END:
127
128 io_uring_queue_exit( &ring );
129
130 ret = close(newsock);
131 if(ret < 0) {
132 perror( "close new" );
133 exit( EXIT_FAILURE );
134 }
135
136 ret = close(sock);
137 if(ret < 0) {
138 perror( "close old" );
139 exit( EXIT_FAILURE );
140 }
141
142 return 0;
143}
Note: See TracBrowser for help on using the repository browser.