~vcs-imports/junkcode/main

« back to all changes in this revision

Viewing changes to messaging/tcp2.c

  • Committer: tridge
  • Date: 2006-08-13 06:50:46 UTC
  • Revision ID: vcs-imports@canonical.com-20060813065046-faca53adb6ad9f49
messaging tests from Mainz

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
   measure latency of tcp sockets
 
3
   tridge@samba.org July 2006
 
4
*/
 
5
 
 
6
#define _GNU_SOURCE
 
7
#include <stdio.h>
 
8
#include <stdlib.h>
 
9
#include <unistd.h>
 
10
#include <stdarg.h>
 
11
#include <fcntl.h>
 
12
#include <sys/ioctl.h>
 
13
#include <sys/types.h>
 
14
#include <sys/socket.h>
 
15
#include <sys/un.h>
 
16
#include <sys/poll.h>
 
17
#include <sys/time.h>
 
18
#include <time.h>
 
19
#include <errno.h>
 
20
#include <netinet/in.h>
 
21
#include <netinet/tcp.h>
 
22
#include <netdb.h>
 
23
#include <arpa/inet.h>
 
24
 
 
25
 
 
26
typedef int BOOL;
 
27
 
 
28
#define True 1
 
29
#define False 0
 
30
 
 
31
static struct timeval tp1,tp2;
 
32
 
 
33
static void start_timer()
 
34
{
 
35
        gettimeofday(&tp1,NULL);
 
36
}
 
37
 
 
38
static double end_timer()
 
39
{
 
40
        gettimeofday(&tp2,NULL);
 
41
        return (tp2.tv_sec + (tp2.tv_usec*1.0e-6)) - 
 
42
                (tp1.tv_sec + (tp1.tv_usec*1.0e-6));
 
43
}
 
44
 
 
45
static void fatal(const char *why)
 
46
{
 
47
        fprintf(stderr, "fatal: %s - %s\n", why, strerror(errno));
 
48
        exit(1);
 
49
}
 
50
 
 
51
enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
 
52
 
 
53
struct
 
54
{
 
55
  char *name;
 
56
  int level;
 
57
  int option;
 
58
  int value;
 
59
  int opttype;
 
60
} socket_options[] = {
 
61
  {"SO_KEEPALIVE",      SOL_SOCKET,    SO_KEEPALIVE,    0,                 OPT_BOOL},
 
62
  {"SO_REUSEADDR",      SOL_SOCKET,    SO_REUSEADDR,    0,                 OPT_BOOL},
 
63
  {"SO_BROADCAST",      SOL_SOCKET,    SO_BROADCAST,    0,                 OPT_BOOL},
 
64
#ifdef TCP_NODELAY
 
65
  {"TCP_NODELAY",       IPPROTO_TCP,   TCP_NODELAY,     0,                 OPT_BOOL},
 
66
#endif
 
67
#ifdef IPTOS_LOWDELAY
 
68
  {"IPTOS_LOWDELAY",    IPPROTO_IP,    IP_TOS,          IPTOS_LOWDELAY,    OPT_ON},
 
69
#endif
 
70
#ifdef IPTOS_THROUGHPUT
 
71
  {"IPTOS_THROUGHPUT",  IPPROTO_IP,    IP_TOS,          IPTOS_THROUGHPUT,  OPT_ON},
 
72
#endif
 
73
#ifdef SO_SNDBUF
 
74
  {"SO_SNDBUF",         SOL_SOCKET,    SO_SNDBUF,       0,                 OPT_INT},
 
75
#endif
 
76
#ifdef SO_RCVBUF
 
77
  {"SO_RCVBUF",         SOL_SOCKET,    SO_RCVBUF,       0,                 OPT_INT},
 
78
#endif
 
79
#ifdef SO_SNDLOWAT
 
80
  {"SO_SNDLOWAT",       SOL_SOCKET,    SO_SNDLOWAT,     0,                 OPT_INT},
 
81
#endif
 
82
#ifdef SO_RCVLOWAT
 
83
  {"SO_RCVLOWAT",       SOL_SOCKET,    SO_RCVLOWAT,     0,                 OPT_INT},
 
84
#endif
 
85
#ifdef SO_SNDTIMEO
 
86
  {"SO_SNDTIMEO",       SOL_SOCKET,    SO_SNDTIMEO,     0,                 OPT_INT},
 
87
#endif
 
88
#ifdef SO_RCVTIMEO
 
89
  {"SO_RCVTIMEO",       SOL_SOCKET,    SO_RCVTIMEO,     0,                 OPT_INT},
 
90
#endif
 
91
  {NULL,0,0,0,0}};
 
92
 
 
93
 
 
94
/****************************************************************************
 
95
  Get the next token from a string, return False if none found
 
96
  handles double-quotes. 
 
97
Based on a routine by GJC@VILLAGE.COM. 
 
98
Extensively modified by Andrew.Tridgell@anu.edu.au
 
99
****************************************************************************/
 
100
BOOL next_token(char **ptr,char *buff,char *sep)
 
101
{
 
102
  char *s;
 
103
  BOOL quoted;
 
104
  static char *last_ptr=NULL;
 
105
 
 
106
  if (!ptr) ptr = &last_ptr;
 
107
  if (!ptr) return(False);
 
108
 
 
109
  s = *ptr;
 
110
 
 
111
  /* default to simple separators */
 
112
  if (!sep) sep = " \t\n\r";
 
113
 
 
114
  /* find the first non sep char */
 
115
  while(*s && strchr(sep,*s)) s++;
 
116
 
 
117
  /* nothing left? */
 
118
  if (! *s) return(False);
 
119
 
 
120
  /* copy over the token */
 
121
  for (quoted = False; *s && (quoted || !strchr(sep,*s)); s++)
 
122
    {
 
123
      if (*s == '\"') 
 
124
        quoted = !quoted;
 
125
      else
 
126
        *buff++ = *s;
 
127
    }
 
128
 
 
129
  *ptr = (*s) ? s+1 : s;  
 
130
  *buff = 0;
 
131
  last_ptr = *ptr;
 
132
 
 
133
  return(True);
 
134
}
 
135
        
 
136
 
 
137
/****************************************************************************
 
138
set user socket options
 
139
****************************************************************************/
 
140
void set_socket_options(int fd, char *options)
 
141
{
 
142
        char tok[200];
 
143
 
 
144
        while (next_token(&options,tok," \t,"))
 
145
    {
 
146
      int ret=0,i;
 
147
      int value = 1;
 
148
      char *p;
 
149
      BOOL got_value = False;
 
150
 
 
151
      if ((p = strchr(tok,'=')))
 
152
        {
 
153
          *p = 0;
 
154
          value = atoi(p+1);
 
155
          got_value = True;
 
156
        }
 
157
 
 
158
      for (i=0;socket_options[i].name;i++)
 
159
        if (strcasecmp(socket_options[i].name,tok)==0)
 
160
          break;
 
161
 
 
162
      if (!socket_options[i].name)
 
163
        {
 
164
          printf("Unknown socket option %s\n",tok);
 
165
          continue;
 
166
        }
 
167
 
 
168
      switch (socket_options[i].opttype)
 
169
        {
 
170
        case OPT_BOOL:
 
171
        case OPT_INT:
 
172
          ret = setsockopt(fd,socket_options[i].level,
 
173
                           socket_options[i].option,(char *)&value,sizeof(int));
 
174
          break;
 
175
 
 
176
        case OPT_ON:
 
177
                if (got_value)
 
178
                        printf("syntax error - %s does not take a value\n",tok);
 
179
 
 
180
          {
 
181
            int on = socket_options[i].value;
 
182
            ret = setsockopt(fd,socket_options[i].level,
 
183
                             socket_options[i].option,(char *)&on,sizeof(int));
 
184
          }
 
185
          break;          
 
186
        }
 
187
      
 
188
      if (ret != 0)
 
189
        printf("Failed to set socket option %s\n",tok);
 
190
    }
 
191
}
 
192
 
 
193
/*
 
194
  connect to a tcp socket
 
195
*/
 
196
int tcp_socket_connect(const char *host, int port)
 
197
{
 
198
        int type = SOCK_STREAM;
 
199
        struct sockaddr_in sock_out;
 
200
        int res;
 
201
        struct hostent *hp;
 
202
 
 
203
        res = socket(PF_INET, type, 0);
 
204
        if (res == -1) {
 
205
                return -1;
 
206
        }
 
207
 
 
208
        hp = gethostbyname(host);
 
209
        if (!hp) {
 
210
                fprintf(stderr,"unknown host: %s\n", host);
 
211
                close(res);
 
212
                return -1;
 
213
        }
 
214
 
 
215
        memcpy(&sock_out.sin_addr, hp->h_addr, hp->h_length);
 
216
        sock_out.sin_port = htons(port);
 
217
        sock_out.sin_family = PF_INET;
 
218
 
 
219
        if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out))) {
 
220
                fprintf(stderr,"failed to connect to %s - %s\n", host, strerror(errno));
 
221
                close(res);
 
222
                return -1;
 
223
        }
 
224
 
 
225
        return res;
 
226
}
 
227
 
 
228
 
 
229
/*
 
230
  create a tcp socket and bind it
 
231
  return a file descriptor open on the socket 
 
232
*/
 
233
static int tcp_socket_bind(int port)
 
234
{
 
235
        struct hostent *hp;
 
236
        struct sockaddr_in sock;
 
237
        char host_name[1000];
 
238
        int res;
 
239
        int one=1;
 
240
 
 
241
        /* get my host name */
 
242
        if (gethostname(host_name, sizeof(host_name)) == -1) { 
 
243
                fprintf(stderr,"gethostname failed\n"); 
 
244
                return -1; 
 
245
        } 
 
246
 
 
247
        /* get host info */
 
248
        if ((hp = gethostbyname(host_name)) == 0) {
 
249
                fprintf(stderr,"gethostbyname: Unknown host %s\n",host_name);
 
250
                return -1;
 
251
        }
 
252
  
 
253
        memset((char *)&sock,0,sizeof(sock));
 
254
        memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length);
 
255
        sock.sin_port = htons(port);
 
256
        sock.sin_family = hp->h_addrtype;
 
257
        sock.sin_addr.s_addr = INADDR_ANY;
 
258
        res = socket(hp->h_addrtype, SOCK_STREAM, 0);
 
259
        if (res == -1) { 
 
260
                fprintf(stderr,"socket failed\n"); 
 
261
                return -1; 
 
262
        }
 
263
 
 
264
        setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
 
265
 
 
266
        /* now we've got a socket - we need to bind it */
 
267
        if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) == -1) { 
 
268
                fprintf(stderr,"bind failed on port %d\n", port);
 
269
                close(res); 
 
270
                return -1;
 
271
        }
 
272
 
 
273
        listen(res, 1);
 
274
 
 
275
        return res;
 
276
}
 
277
 
 
278
/*
 
279
  accept on a tcp socket
 
280
*/
 
281
static int tcp_socket_accept(int fd)
 
282
{
 
283
        struct sockaddr a;
 
284
        socklen_t len;
 
285
        return accept(fd, &a, &len);
 
286
}
 
287
 
 
288
static void worker(const char *host, int port1, int port2, int w)
 
289
{
 
290
        int l = tcp_socket_bind(port1);
 
291
        int s2, s1;
 
292
        int count=0;
 
293
 
 
294
        set_socket_options(l, "SO_REUSEADDR");
 
295
 
 
296
        sleep(2);
 
297
 
 
298
        s2 = tcp_socket_connect(host, port2);
 
299
        s1 = tcp_socket_accept(l);
 
300
 
 
301
        set_socket_options(s1, "TCP_NODELAY");
 
302
        set_socket_options(s2, "TCP_NODELAY");
 
303
 
 
304
        start_timer();
 
305
 
 
306
        while (1) {
 
307
                char c=0;
 
308
                if (write(s2, &c, 1) != 1) {
 
309
                        fatal("write");
 
310
                }
 
311
                if (read(s1, &c, 1) != 1) {
 
312
                        fatal("read");
 
313
                }
 
314
                if (w == 1 && (end_timer() > 1.0)) {
 
315
                        printf("%8u ops/sec\r", 
 
316
                               (unsigned)(2*count/end_timer()));
 
317
                        fflush(stdout);
 
318
                        start_timer();
 
319
                        count=0;
 
320
                }
 
321
                count++;
 
322
        }
 
323
}
 
324
 
 
325
int main(int argc, char *argv[])
 
326
{
 
327
        worker(argv[1], atoi(argv[2]), atoi(argv[3]), 1);
 
328
        return 0;
 
329
}