| /* Licensed to the Apache Software Foundation (ASF) under one or more | |
| * contributor license agreements. See the NOTICE file distributed with | |
| * this work for additional information regarding copyright ownership. | |
| * The ASF licenses this file to You under the Apache License, Version 2.0 | |
| * (the "License"); you may not use this file except in compliance with | |
| * the License. You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| /* | |
| test-writev: use this to figure out if your writev() does intelligent | |
| things on the network. Some writev()s when given multiple buffers | |
| will break them up into multiple packets, which is a waste. | |
| Linux prior to 2.0.31 has this problem. | |
| Solaris 2.5, 2.5.1 doesn't appear to, 2.6 hasn't been tested. | |
| IRIX 5.3 doesn't have this problem. | |
| To use this you want to snoop the wire with tcpdump, and then run | |
| "test-writev a.b.c.d port#" ... against some TCP service on another | |
| box. For example you can run it against port 80 on another server. | |
| You want to look to see how many data packets are sent, you're hoping | |
| only one of size 300 is sent. | |
| */ | |
| #include <stdio.h> | |
| #include <sys/types.h> | |
| #include <sys/socket.h> | |
| #include <netinet/in.h> | |
| #include <stdlib.h> | |
| #include <unistd.h> | |
| #include <arpa/inet.h> | |
| #include <sys/uio.h> | |
| #include <errno.h> | |
| #ifndef INADDR_NONE | |
| #define INADDR_NONE (-1ul) | |
| #endif | |
| void main( int argc, char **argv ) | |
| { | |
| struct sockaddr_in server_addr; | |
| int s; | |
| struct iovec vector[3]; | |
| char buf[100]; | |
| int i; | |
| const int just_say_no = 1; | |
| if( argc != 3 ) { | |
| usage: | |
| fprintf( stderr, "usage: test-writev a.b.c.d port#\n" ); | |
| exit( 1 ); | |
| } | |
| server_addr.sin_family = AF_INET; | |
| server_addr.sin_addr.s_addr = inet_addr( argv[1] ); | |
| if( server_addr.sin_addr.s_addr == INADDR_NONE ) { | |
| fprintf( stderr, "bogus address\n" ); | |
| goto usage; | |
| } | |
| server_addr.sin_port = htons( atoi( argv[2] ) ); | |
| s = socket( AF_INET, SOCK_STREAM, 0 ); | |
| if( s < 0 ) { | |
| perror("socket"); | |
| exit(1); | |
| } | |
| if( connect( s, (struct sockaddr *)&server_addr, sizeof( server_addr ) ) | |
| != 0 ) { | |
| perror("connect"); | |
| exit(1); | |
| } | |
| if( setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char*)&just_say_no, | |
| sizeof(just_say_no)) != 0 ) { | |
| perror( "TCP_NODELAY" ); | |
| exit(1); | |
| } | |
| /* now build up a two part writev and write it out */ | |
| for( i = 0; i < sizeof( buf ); ++i ) { | |
| buf[i] = 'x'; | |
| } | |
| vector[0].iov_base = buf; | |
| vector[0].iov_len = sizeof(buf); | |
| vector[1].iov_base = buf; | |
| vector[1].iov_len = sizeof(buf); | |
| vector[2].iov_base = buf; | |
| vector[2].iov_len = sizeof(buf); | |
| i = writev( s, &vector[0], 3 ); | |
| fprintf( stdout, "i=%d, errno=%d\n", i, errno ); | |
| exit(0); | |
| } |