| /* |
| * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 <pthread.h> |
| #include <string.h> |
| #include "inet.h" |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <stdint.h> |
| |
| #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(sockfd) |
| 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]; |
| |
| 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 ( (void *) 0); |
| } |