You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
184 lines
5.2 KiB
184 lines
5.2 KiB
/*
|
|
* 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 <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(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);
|
|
}
|