| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- #include <time.h>
- #include <stdio.h>
- #include <signal.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <pthread.h>
- #include <arpa/inet.h>
- #include <sys/socket.h>
- const uint16_t SERVER_PORT = 1092;
- const int MAX_CLIENT_NUM = 20;
- const int MESSAGE_LEN = 256;
- const int HEADER_LEN = 4;
- int serv_sock;
- int clnt_socks[MAX_CLIENT_NUM];
- struct sockaddr_in clnt_addrs[MAX_CLIENT_NUM];
- struct message
- {
- uint8_t opcode, status;
- uint16_t length;
- char data[MESSAGE_LEN - HEADER_LEN];
- };
- struct client
- {
- uint16_t id, port;
- uint32_t addr;
- };
- void send_message(int clnt_sock, uint8_t opcode, uint8_t status, uint16_t length, char data[])
- {
- struct message msg;
- msg.opcode = opcode;
- msg.status = status;
- msg.length = htons(length);
- memcpy(msg.data, data, length);
- write(clnt_sock, &msg, MESSAGE_LEN);
- }
- void *conn(void *id)
- {
- uint16_t clnt_id = *(uint16_t *)id;
- int clnt_sock = clnt_socks[clnt_id];
- char data[MESSAGE_LEN];
- sprintf(data, "Hello, client %hu.", clnt_id);
- send_message(clnt_sock, 0, 1, strlen(data), data);
- for (;;)
- {
- struct message msg;
- int expect = MESSAGE_LEN;
- for (char *p = (char *)&msg; expect > 0;)
- {
- int len = read(clnt_sock, p, expect);
- if (len <= 0)
- {
- break;
- }
- expect -= len;
- p += len;
- }
- if (expect > 0)
- {
- break;
- }
- printf("Receive message from client %hu. opcode = %hu.\n", clnt_id, msg.opcode);
- switch (msg.opcode)
- {
- case 1:
- {
- time_t now;
- time(&now);
- strcpy(data, ctime(&now));
- send_message(clnt_sock, 1, 1, strlen(data) - 1, data);
- break;
- }
- case 2:
- {
- gethostname(data, MESSAGE_LEN);
- send_message(clnt_sock, 2, 1, strlen(data), data);
- break;
- }
- case 3:
- {
- int cnt = 0;
- for (uint16_t i = 0; i < MAX_CLIENT_NUM; i++)
- {
- if (clnt_socks[i] != -1)
- {
- ((struct client *)data)[cnt].id = htons(i);
- ((struct client *)data)[cnt].addr = clnt_addrs[i].sin_addr.s_addr;
- ((struct client *)data)[cnt].port = clnt_addrs[i].sin_port;
- cnt++;
- }
- }
- send_message(clnt_sock, 3, 1, sizeof(struct client) * cnt, data);
- break;
- }
- case 4:
- {
- uint16_t id = ntohs(((uint16_t *)msg.data)[0]);
- if (clnt_socks[id] == -1)
- {
- send_message(clnt_sock, 4, 2, 0, NULL);
- }
- else
- {
- ((uint16_t *)msg.data)[0] = htons(clnt_id);
- send_message(clnt_sock, 4, 1, 0, NULL);
- send_message(clnt_socks[id], 0, 0, strlen(msg.data + 2) + 2, msg.data);
- printf(" Forward message to client %hu.\n", id);
- }
- break;
- }
- default:
- {
- sprintf(data, "Invalid operation.");
- send_message(clnt_sock, 0, 2, strlen(data), data);
- }
- }
- }
- close(clnt_sock);
- printf("Client %hu disconnected.\n", clnt_id);
- clnt_socks[clnt_id] = -1;
- return NULL;
- }
- void stop_server(int sig)
- {
- for (uint16_t i = 0; i < MAX_CLIENT_NUM; i++)
- {
- if (clnt_socks[i] != -1)
- {
- close(clnt_socks[i]);
- printf("Client %hu disconnected.\n", i);
- clnt_socks[i] = -1;
- }
- }
- close(serv_sock);
- puts("Stop listening.");
- exit(0);
- }
- int main()
- {
- memset(clnt_socks, -1, sizeof(clnt_socks));
- serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (serv_sock == -1)
- {
- puts("Create socket failed.");
- exit(1);
- }
- struct sockaddr_in serv_addr;
- memset(&serv_addr, 0, sizeof(serv_addr));
- serv_addr.sin_family = AF_INET;
- serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
- serv_addr.sin_port = htons(SERVER_PORT);
- if (bind(serv_sock, (const struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1)
- {
- puts("Bind socket failed.");
- exit(1);
- }
- if (listen(serv_sock, MAX_CLIENT_NUM) == -1)
- {
- puts("Listen socket failed.");
- exit(1);
- }
- puts("Start listening on port 1092...");
- signal(SIGINT, stop_server);
- for (;;)
- {
- struct sockaddr_in clnt_addr;
- socklen_t clnt_addr_size = sizeof(clnt_addr);
- int clnt_sock = accept(serv_sock, (struct sockaddr *)&clnt_addr, &clnt_addr_size);
- if (clnt_sock == -1)
- {
- puts("Create socket failed.");
- continue;
- }
- for (uint16_t i = 0; i < MAX_CLIENT_NUM; i++)
- {
- if (clnt_socks[i] == -1)
- {
- clnt_socks[i] = clnt_sock;
- clnt_addrs[i] = clnt_addr;
- pthread_t pid;
- if (pthread_create(&pid, NULL, conn, &i) != 0)
- {
- puts("Create thread failed.");
- clnt_socks[i] = -1;
- break;
- }
- printf("Client %hu (%s:%hu) connected. pid = %lu.\n", i, inet_ntoa(clnt_addr.sin_addr), ntohs(clnt_addr.sin_port), pid);
- break;
- }
- }
- }
- return 0;
- }
|