source: examples/io/server.c @ 6c6e36c

ADTarm-ehast-experimentalenumforall-pointer-decayjacob/cs343-translationnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since 6c6e36c was 6c6e36c, checked in by Thierry Delisle <tdelisle@…>, 4 years ago

Added async server using io_uring and a dummy client to go with it

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