/* * Copyright (c) International Business Machines Corp., 2001 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* * File: pthserv.c Version: 1.3 Last update: 5/19/94 08:55:35 */ /******************************************************************************/ /* File: pthserv.c */ /* */ /* Description: Read a stream socket one line at a time and write each line */ /* back to the sender. */ /* */ /* History: Contact - 06/21/2001 - Manoj Iyeri, IBM Austin */ /* */ /* Usage: pthcli [port number] */ /* */ /******************************************************************************/ /* TCP server */ #include #include #include "inet.h" #include #include #include #define MAXLINE 1024 void noprintf(char *string, ...) { } pthread_t th; pthread_mutex_t current_mutex; int sockfd; /* Read a stream socket one line at a time and write each line back to sender. Return when connection is terminated */ int str_echo(int sockfd) { int n, testint; char line[MAXLINE]; printf("sockfd = %d\n", sockfd); for (;;) { prtln(); dprt2(("%s: str_echo(): reading from sockfd %d\n", __FILE__, sockfd)); n = readline(sockfd, line, MAXLINE); printf("str_echo: n = %d\n", n); if (n == 0) { dprt2(("%s: str_echo(): connection terminated\n", __FILE__)); return 0; /* connection terminated */ } else if (n < 0) { perror("str_echo: readline error"); return (-1); } dprt2(("%s: str_echo(): writing to sockfd = %d\n", __FILE__, sockfd)); testint = writen(sockfd, line, n); prtln(); if (testint != n) { perror("str_echo: writen error"); return (-1); } prtln(); } } int main(int argc, char *argv[]) { void *new_thread(void *); pthread_attr_t newattr; int newsockfd; socklen_t clilen; struct sockaddr_in cli_addr, serv_addr; pname = argv[0]; (void) argc; prtln(); /* Open inet stream socket */ if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("server: socket failure:"); exit(1); } prtln(); dprt2(("%s: main(): Open inet stream socket sockfd = %d\n", __FILE__, sockfd)); /* Bind local address for client to use */ memset((char *)&serv_addr, 0x00, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(SERV_TCP_PORT); prtln(); dprt2(("%s: main(): Binding local address for client to use\n" "serv_addr.sin_family = %d\n serv_addr.sin_addr.s_addr = %#x\n" "serv_addr.sin_port = %d\n", __FILE__, serv_addr.sin_family, serv_addr.sin_addr.s_addr, serv_addr.sin_port)); prtln(); if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { printf("server bind failure:\n"); fflush(NULL); exit(1); } prtln(); if (pthread_mutex_init(¤t_mutex, NULL) != 0) printf("current_mutex_init() failure"); prtln(); /* attr init, detached state create thread */ if (pthread_attr_init(&newattr)) printf("failure to init attributes\n"); if (pthread_attr_setdetachstate(&newattr, PTHREAD_CREATE_DETACHED)) printf("failure to set detached state\n"); prtln(); listen(sockfd, 5); prtln(); for (;;) { /* Wait for connection from a client process */ clilen = sizeof(cli_addr); newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen); prtln(); if (newsockfd < 0) { perror("server: accept"); printf("server: accept error"); exit(1); } else { /* create thread to handle client request */ if (pthread_create(&th, &newattr, new_thread, (void *)(uintptr_t) newsockfd)) printf("failure to create thread\n"); #ifndef _LINUX yield(); #else sched_yield(); #endif } prtln(); } close(sockfd); } void *new_thread(void *arg_) { int arg = (uintptr_t) arg_; if (pthread_mutex_lock(¤t_mutex)) printf("mutex_lock failed"); if (str_echo(arg) < 0) /* process the request */ printf("new_thread: str_echo returned error"); close(arg); /* i.e. newsockfd */ if (pthread_mutex_unlock(¤t_mutex)) printf("mutex_unlock failed"); #ifndef _LINUX yield(); #else sched_yield(); #endif pthread_exit(NULL); }