-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.c
130 lines (116 loc) · 3.5 KB
/
server.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/* z523087 - Final project SnakeIT server, based on Class 9 socket server */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdbool.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stddef.h> /* size_t */
#include <ncurses.h> /* for KeyboardInput structure contents */
typedef struct {
int key;
time_t timestamp;
unsigned long checksum;
} KeyboardInput;
typedef struct {
int X;
int Y;
int score;
uint16_t port;
} GameState;
int main(int argc, char *argv[]) {
int sockfd, len, new_sockfd, pipefd[2];
char buf[BUFSIZ];
struct sockaddr_in serv, clnt;
socklen_t sin_siz;
int port;
if (argc != 3) {
printf("Usage: ./server.elf host port\n");
exit(1);
}
if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
exit(1);
}
printf("socket() called\n");
serv.sin_family = PF_INET;
port = strtol(argv[2], NULL, 10);
serv.sin_port = htons(port);
inet_aton(argv[1], &serv.sin_addr);
sin_siz = sizeof(struct sockaddr_in);
if (bind(sockfd, (struct sockaddr * ) &serv, sizeof(serv)) < 0) {
perror("bind");
exit(1);
}
printf("bind() called\n");
if (listen(sockfd, SOMAXCONN) < 0) {
perror("listen");
exit(1);
}
printf("listen() called\n");
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
while (1) {
if ((new_sockfd = accept(sockfd, (struct sockaddr *) &clnt, &sin_siz)) < 0) {
perror("accept");
}
printf("connect from %s: %d\n", inet_ntoa(clnt.sin_addr), ntohs(clnt.sin_port));
memset(buf, 0, BUFSIZ);
pid_t pid = fork();
if (pid < 0) {
perror("fork failed");
exit(1);
} else if (pid == 0) {
close(sockfd);
close(pipefd[0]); /* Close read end of pipe in child */
bool keepRunning = true;
KeyboardInput ki;
GameState gs;
gs.X = 0;
gs.Y = 0;
gs.score = 0;
gs.port = ntohs(clnt.sin_port); /* Add player's port to GameState */
while ((recv(new_sockfd, (char*)&ki, sizeof(ki), 0) > 0 ) && keepRunning) { /* Receive KeyboardInput from client */
switch (ki.key) {
case KEY_UP:
gs.Y--;
break;
case KEY_DOWN:
gs.Y++;
break;
case KEY_LEFT:
gs.X--;
break;
case KEY_RIGHT:
gs.X++;
break;
case 'q':
case 'Q':
keepRunning = false; /* Would be simpler to "goto" outside of this while loop, but less elegant. */
break;
}
write(pipefd[1], (char*)&gs, sizeof(gs)); /* Write game state to pipe */
len = send(sockfd, (char*)&gs, sizeof(gs), 0); /* Send game state to client */
}
printf("client/player on port %s disconnected.", gs.port);
close(pipefd[1]); /* Close write end of pipe in child */
close(new_sockfd); /* Added post-demo - I forgot this, overwrote when adding pipe capabilites*/
exit(0);
} else {
continue;
}
}
close(sockfd);
close(pipefd[1]); /* Close write end of pipe in parent */
GameState gs;
while (read(pipefd[0], (char*)&gs, sizeof(gs)) > 0) {
printf("Player position: (%d, %d) Port: %d\n", gs.X, gs.Y, gs.port);
}
close(pipefd[0]); /* Close read end of pipe in parent */
return 0;
}