1 /*
2 * a stream socket server demo
3 */
4
5
6 #include <arpa/inet.h>
7 #include <errno.h>
8 #include <netinet/in.h>
9 #include <signal.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <sys/socket.h>
14 #include <sys/types.h>
15 #include <sys/wait.h>
16 #include <unistd.h>
17
18
19 #define MYPORT 1234 // the port users will be connecting to
20 #define BACKLOG 10 // how many pending connections queue will hold
21 #define MAXDATASIZE 1065537
22
23
24 static void
sigchld_handler(int s)25 sigchld_handler(int s)
26 {
27 while (waitpid(-1, NULL, WNOHANG) > 0) {
28 }
29 }
30
31
32 int
main(int argc,char * argv[])33 main(int argc, char *argv[])
34 {
35 int sockfd, new_fd; // listen on sock_fd, new connection on new_fd
36 struct sockaddr_in my_addr; // my address information
37 struct sockaddr_in their_addr; // connector's address information
38 uint32_t sin_size;
39 struct sigaction sa;
40 int yes = 1;
41 short int port = MYPORT;
42 char buf[MAXDATASIZE];
43
44 if (argc >= 2 && atoi(argv[1]) != 0)
45 port = atoi(argv[1]);
46
47 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
48 perror("socket");
49 exit(1);
50 }
51
52 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
53 perror("setsockopt");
54 exit(1);
55 }
56
57 memset(&my_addr, 0, sizeof(my_addr));
58 my_addr.sin_family = AF_INET;
59 my_addr.sin_port = htons(port);
60 my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
61
62 if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
63 perror("bind");
64 exit(1);
65 }
66
67 if (listen(sockfd, BACKLOG) == -1) {
68 perror("listen");
69 exit(1);
70 }
71
72 sa.sa_handler = sigchld_handler; // reap all dead processes
73 sigemptyset(&sa.sa_mask);
74 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
75 sa.sa_flags = SA_RESTART;
76 #else
77 sa.sa_flags = 0;
78 #endif
79 if (sigaction(SIGCHLD, &sa, NULL) == -1) {
80 perror("sigaction");
81 exit(1);
82 }
83
84 while (1) {
85 // main accept() loop
86 sin_size = sizeof(struct sockaddr_in);
87 if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) {
88 perror("accept");
89 continue;
90 }
91 printf("server: got connection from %s\n", inet_ntoa(their_addr.sin_addr));
92 if (!fork()) { // this is the child process
93 close(sockfd); // child doesn't need the listener
94
95 if (!fork()) {
96 while (1) {
97 // child's child process
98 if (fgets(buf, MAXDATASIZE, stdin) == NULL) {
99 perror("fgets");
100 exit(1);
101 }
102
103 if (!strcmp(buf, "full\n")) {
104 int i;
105 puts("HY");
106 for (i = 0; i < MAXDATASIZE - 2; i++) {
107 buf[i] = 'a' + (i % 26);
108 }
109 buf[MAXDATASIZE - 2] = '\n';
110 buf[MAXDATASIZE - 1] = '\0';
111 }
112
113 if (send(new_fd, buf, strlen(buf), 0) == -1) {
114 perror("send");
115 exit(1);
116 }
117 }
118 } else {
119 ssize_t numBytes;
120 while (1) {
121 // child process
122 if ((numBytes = recv(new_fd, buf, MAXDATASIZE, 0)) == -1) {
123 perror("recv");
124 exit(1);
125 }
126 if (numBytes == 0)
127 exit(0);
128
129 buf[numBytes] = '\0';
130
131 printf("%s:| %s", inet_ntoa(their_addr.sin_addr), buf);
132 }
133 }
134
135 close(new_fd);
136 exit(0);
137 }
138 close(new_fd); // parent doesn't need this
139 }
140
141 return 0;
142 }
143
144