server.c (3485B)
1 #include <stdio.h> 2 #include <string.h> 3 #include <unistd.h> 4 #include <poll.h> 5 #include <signal.h> 6 #include <errno.h> 7 8 #include <sys/socket.h> 9 #include <netinet/in.h> 10 11 #define MAX_CLIENTS 16 12 #define BUFFER_SIZE 1024 13 14 void remove_client(struct pollfd *fds, int *client_count, int index) { 15 int i; 16 17 close(fds[index].fd); 18 19 for (i = index; i < *client_count; i++) { 20 fds[i] = fds[i + 1]; 21 } 22 23 (*client_count)--; 24 } 25 26 int main() { 27 int server_fd; 28 int client_fd; 29 int client_count; 30 int i; 31 int j; 32 int n; 33 int result; 34 int opt; 35 struct sockaddr_in addr; 36 struct pollfd fds[MAX_CLIENTS + 1]; 37 char buffer[BUFFER_SIZE]; 38 39 signal(SIGPIPE, SIG_IGN); 40 41 server_fd = socket(AF_INET, SOCK_STREAM, 0); 42 if (server_fd == -1) { 43 perror("socket"); 44 return 1; 45 } 46 47 opt = 1; 48 49 if (setsockopt( 50 server_fd, 51 SOL_SOCKET, 52 SO_REUSEADDR, 53 &opt, 54 sizeof(opt) 55 ) == -1) { 56 perror("setsockopt"); 57 close(server_fd); 58 return 1; 59 } 60 61 memset(&addr, 0, sizeof(addr)); 62 63 addr.sin_family = AF_INET; 64 addr.sin_port = htons(8080); 65 addr.sin_addr.s_addr = htonl(INADDR_ANY); 66 67 if (bind(server_fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { 68 perror("bind"); 69 close(server_fd); 70 return 1; 71 } 72 73 if (listen(server_fd, 16) == -1) { 74 perror("listen"); 75 close(server_fd); 76 return 1; 77 } 78 79 memset(fds, 0, sizeof(fds)); 80 81 fds[0].fd = server_fd; 82 fds[0].events = POLLIN; 83 84 client_count = 0; 85 86 printf("listening on port 8080\n"); 87 88 while (1) { 89 result = poll(fds, client_count + 1, -1); 90 91 if (result == -1) { 92 if (errno == EINTR) { 93 continue; 94 } 95 96 perror("poll"); 97 break; 98 } 99 100 /* 101 * New client. 102 */ 103 if (fds[0].revents & POLLIN) { 104 client_fd = accept(server_fd, NULL, NULL); 105 106 if (client_fd == -1) { 107 perror("accept"); 108 } else if (client_count >= MAX_CLIENTS) { 109 printf("too many clients\n"); 110 close(client_fd); 111 } else { 112 client_count++; 113 114 fds[client_count].fd = client_fd; 115 fds[client_count].events = POLLIN; 116 117 printf("client %d connected\n", client_fd); 118 } 119 } 120 121 /* 122 * Existing clients. 123 */ 124 for (i = 1; i <= client_count; i++) { 125 /* 126 * Error or disconnect. 127 */ 128 if (fds[i].revents & (POLLERR | POLLHUP | POLLNVAL)) { 129 printf("client %d disconnected\n", fds[i].fd); 130 131 remove_client(fds, &client_count, i); 132 i--; 133 134 continue; 135 } 136 137 if (!(fds[i].revents & POLLIN)) { 138 continue; 139 } 140 141 n = recv( 142 fds[i].fd, 143 buffer, 144 sizeof(buffer), 145 0 146 ); 147 148 if (n == -1) { 149 if (errno == EINTR) { 150 continue; 151 } 152 153 perror("recv"); 154 155 remove_client(fds, &client_count, i); 156 i--; 157 158 continue; 159 } 160 161 if (n == 0) { 162 printf("client %d disconnected\n", fds[i].fd); 163 164 remove_client(fds, &client_count, i); 165 i--; 166 167 continue; 168 } 169 170 printf( 171 "client %d sent %d bytes\n", 172 fds[i].fd, 173 n 174 ); 175 176 /* 177 * Broadcast. 178 */ 179 for (j = 1; j <= client_count; j++) { 180 if (j == i) { 181 continue; 182 } 183 184 if (send( 185 fds[j].fd, 186 buffer, 187 n, 188 MSG_NOSIGNAL 189 ) == -1) { 190 perror("send"); 191 } 192 } 193 } 194 } 195 196 for (i = 1; i <= client_count; i++) { 197 close(fds[i].fd); 198 } 199 200 close(server_fd); 201 202 return 0; 203 }