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
24static void
25sigchld_handler(int s)
26{
27	while (waitpid(-1, NULL, WNOHANG) > 0) {
28	}
29}
30
31
32int
33main(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;
105puts("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