File: sockettestServer.cxx

package info (click to toggle)
timblserver 1.4-2
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 1,852 kB
  • sloc: sh: 11,006; cpp: 3,067; makefile: 37
file content (185 lines) | stat: -rw-r--r-- 5,325 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
/*
  Copyright (c) 1998 - 2011
  ILK  -  Tilburg University
  CNTS -  University of Antwerp
 
  This file is part of timblserver

  timblserver 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 3 of the License, or
  (at your option) any later version.

  timblserver 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, see <http://www.gnu.org/licenses/>.

  For questions and suggestions, see:
      http://ilk.uvt.nl/software.html
  or send mail to:
      timbl@uvt.nl
*/

#include <string>
#include <cstdlib>
#include <cstdio>
#include <signal.h>
#include <iostream>
#include "timbl/Types.h"
#include "timblserver/SocketBasics.h"

using namespace std;

//
// a simple program to demonstrate and test the Timbl Socket interface
//

int globalTimeOut = 0; // evil

void *do_child( void *arg ){
  Sockets::Socket *mysock = (Sockets::Socket*)arg;
  // Greeting message for the client
  //
  //
  mysock->write( "Welcome to the Timbl socket tester.\n" );
  // process the test material
  //
  char line[256];
  sprintf( line, "Server: Thread %lu, on Socket %d", 
	   (uintptr_t)pthread_self(),
	   mysock->getSockId() );
  cerr << line << ", started" << endl;
  string buf;
  while( mysock->read( buf ) ){
    cerr << "Server: read()" << buf << endl;
    string answer = string( "echo: " ) + buf + "\n"; 
    mysock->write( answer );
    cerr << "Server: wrote()" << answer << endl;
  }
  if ( !mysock->getMessage().empty() )
    cerr << "Server result: " << mysock->getMessage() << endl;
  delete mysock;
  return NULL;
}

int randomSecs(){
  long int r = random();
  ldiv_t dif = ldiv( r, 5 );
  return abs(dif.rem);
}

void *do_to_child( void *arg ){
  Sockets::Socket *mysock = (Sockets::Socket*)arg;
  // Greeting message for the client
  //
  //
  int timeOut = globalTimeOut;
  int snorr = randomSecs();
  cerr << "Server sleeps " << snorr << " seconds" << endl;
  sleep( snorr);
  mysock->write( "Welcome to the Timbl socket tester.\n", timeOut );
  // process the test material
  //
  char line[256];
  sprintf( line, "ToServer: Thread %lu, on Socket %d", 
	   (uintptr_t)pthread_self(),
	   mysock->getSockId() );
  cerr << line << ", started" << endl;
  string buf;
  while( mysock->read( buf, timeOut ) ){
    cerr << "ToServer: read()" << buf << endl;
    string answer = string( "echo: " ) + buf + "\n"; 
    int snorr = randomSecs();
    cerr << "Server sleeps " << snorr << " seconds" << endl;
    sleep( snorr);
    mysock->write( answer, timeOut );
    cerr << "ToServer: wrote()" << answer << endl;
  }
  if ( !mysock->getMessage().empty() )
    cerr << "Toserver result: " << mysock->getMessage() << endl;
  delete mysock;
  return NULL;
}

bool startServer( const string& portString ){
  Sockets::ServerSocket server;
  pthread_attr_t attr;
  if ( pthread_attr_init(&attr) ||
       pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED ) ){
    cerr  << "Threads: couldn't set attributes" << endl;
    return false;
  }
  if ( !server.connect( portString ) ){
    cerr << "failed to start Server: " << server.getMessage() << endl;
    return false;
  }
  
  if ( !server.listen( 5 ) ) {
    // maximum of 5 pending requests
    cerr << server.getMessage() << endl;
    return false;
  }
  
  cerr << "Started Server on port:" << portString << endl;
  int failcount = 0;
  while( true ){ // waiting for connections loop
    signal( SIGPIPE, SIG_IGN );
    Sockets::ServerSocket *newSocket = new Sockets::ServerSocket();
    if ( !server.accept( *newSocket ) ){
      cerr << server.getMessage() << endl;
      if ( ++failcount > 20 ){
	cerr << "accept failcount >20 " << endl;
	cerr << "server stopped." << endl;
	return false;
	}
      else {
	continue;  
      }
    }
    else {
      failcount = 0;
      cerr  << "Server: Accepting Connection #" << newSocket->getSockId()
	    << " from remote host: " << newSocket->getClientName() << endl;
      // create a new thread to process the incoming request 
      // (The thread will terminate itself when done processing
      // and release its socket handle)
      //
      pthread_t chld_thr;
      if ( globalTimeOut > 0 ){
	newSocket->setNonBlocking();
	pthread_create( &chld_thr, &attr, do_to_child, (void *)newSocket );
      }
      else
	pthread_create( &chld_thr, &attr, do_child, (void *)newSocket );
    }
    // the server is now free to accept another socket request 
  }
  pthread_attr_destroy(&attr); 
  return true;
}

int main( int argc, const char *argv[] ){
  string port = "1234";
  string tos = "0";
  if ( argc > 1 )
    port = argv[1];
  if ( argc > 2 )
    tos = argv[2];
  int timeOut;
  if ( !Timbl::stringTo<int>( tos, timeOut ) ){
    cerr << "invalid timeout" << endl;
    cerr << "usage: " << argv[0] << " <port> <timeout>" << endl;
    return 1;
  }
  else
    globalTimeOut = timeOut;
  if ( !startServer( port ) ){
    cerr << "creating server failed" << endl;
  }
  cerr << "Server DONE" << endl;
  return 0;
}