1 /* 2 * Copyright (c) International Business Machines Corp., 2001 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 12 * the GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 /* 19 * File: pthserv.c Version: 1.3 Last update: 5/19/94 08:55:35 20 */ 21 /******************************************************************************/ 22 /* File: pthserv.c */ 23 /* */ 24 /* Description: Read a stream socket one line at a time and write each line */ 25 /* back to the sender. */ 26 /* */ 27 /* History: Contact - 06/21/2001 - Manoj Iyeri, IBM Austin */ 28 /* */ 29 /* Usage: pthcli [port number] */ 30 /* */ 31 /******************************************************************************/ 32 33 /* 34 TCP server 35 */ 36 37 #include <pthread.h> 38 #include <string.h> 39 #include "inet.h" 40 #include <stdlib.h> 41 #include <unistd.h> 42 #include <stdint.h> 43 44 #define MAXLINE 1024 45 void noprintf(char *string, ...) 46 { 47 } 48 49 pthread_t th; 50 pthread_mutex_t current_mutex; 51 int sockfd; 52 53 /* Read a stream socket one line at a time and write each line back 54 to sender. Return when connection is terminated */ 55 56 int str_echo(sockfd) 57 int sockfd; 58 { 59 int n, testint; 60 char line[MAXLINE]; 61 62 printf("sockfd = %d\n", sockfd); 63 for (;;) { 64 prtln(); 65 dprt2(("%s: str_echo(): reading from sockfd %d\n", __FILE__, 66 sockfd)); 67 n = readline(sockfd, line, MAXLINE); 68 printf("str_echo: n = %d\n", n); 69 if (n == 0) { 70 dprt2(("%s: str_echo(): connection terminated\n", 71 __FILE__)); 72 return 0; /* connection terminated */ 73 } else if (n < 0) { 74 perror("str_echo: readline error"); 75 return (-1); 76 } 77 dprt2(("%s: str_echo(): writing to sockfd = %d\n", __FILE__, 78 sockfd)); 79 testint = writen(sockfd, line, n); 80 prtln(); 81 if (testint != n) { 82 perror("str_echo: writen error"); 83 return (-1); 84 } 85 prtln(); 86 } 87 } 88 89 int main(int argc, char *argv[]) 90 { 91 void *new_thread(void *); 92 pthread_attr_t newattr; 93 int newsockfd; 94 socklen_t clilen; 95 struct sockaddr_in cli_addr, serv_addr; 96 pname = argv[0]; 97 98 prtln(); 99 /* Open inet stream socket */ 100 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 101 printf("server: socket failure:"); 102 exit(1); 103 } 104 prtln(); 105 dprt2(("%s: main(): Open inet stream socket sockfd = %d\n", __FILE__, 106 sockfd)); 107 108 /* Bind local address for client to use */ 109 memset((char *)&serv_addr, 0x00, sizeof(serv_addr)); 110 serv_addr.sin_family = AF_INET; 111 serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); 112 serv_addr.sin_port = htons(SERV_TCP_PORT); 113 prtln(); 114 dprt2(("%s: main(): Binding local address for client to use\n" 115 "serv_addr.sin_family = %d\n serv_addr.sin_addr.s_addr = %#x\n" 116 "serv_addr.sin_port = %d\n", __FILE__, serv_addr.sin_family, 117 serv_addr.sin_addr.s_addr, serv_addr.sin_port)); 118 119 prtln(); 120 if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { 121 printf("server bind failure:\n"); 122 fflush(NULL); 123 exit(1); 124 } 125 126 prtln(); 127 if (pthread_mutex_init(¤t_mutex, NULL) != 0) 128 printf("current_mutex_init() failure"); 129 prtln(); 130 131 /* attr init, detached state create thread */ 132 if (pthread_attr_init(&newattr)) 133 printf("failure to init attributes\n"); 134 if (pthread_attr_setdetachstate(&newattr, PTHREAD_CREATE_DETACHED)) 135 printf("failure to set detached state\n"); 136 prtln(); 137 listen(sockfd, 5); 138 139 prtln(); 140 for (;;) { 141 /* Wait for connection from a client process */ 142 clilen = sizeof(cli_addr); 143 144 newsockfd = 145 accept(sockfd, (struct sockaddr *)&cli_addr, &clilen); 146 prtln(); 147 if (newsockfd < 0) { 148 perror("server: accept"); 149 printf("server: accept error"); 150 exit(1); 151 } else { /* create thread to handle client request */ 152 153 if (pthread_create(&th, &newattr, new_thread, 154 (void *)(uintptr_t) newsockfd)) 155 printf("failure to create thread\n"); 156 #ifndef _LINUX 157 yield(); 158 #else 159 sched_yield(); 160 #endif 161 } 162 prtln(); 163 } 164 close(sockfd); 165 } 166 167 void *new_thread(void *arg_) 168 { 169 int arg = (uintptr_t) arg_; 170 if (pthread_mutex_lock(¤t_mutex)) 171 printf("mutex_lock failed"); 172 if (str_echo(arg) < 0) /* process the request */ 173 printf("new_thread: str_echo returned error"); 174 close(arg); /* i.e. newsockfd */ 175 if (pthread_mutex_unlock(¤t_mutex)) 176 printf("mutex_unlock failed"); 177 #ifndef _LINUX 178 yield(); 179 #else 180 sched_yield(); 181 #endif 182 pthread_exit(NULL); 183 } 184