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 25 sigchld_handler(int s) 26 { 27 while (waitpid(-1, NULL, WNOHANG) > 0) { 28 } 29 } 30 31 32 int 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