Last active
February 22, 2017 08:50
-
-
Save pandax381/05a721ae415d49e362d8c9a3ba021334 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <sys/socket.h> | |
#include <sys/types.h> | |
#include <netinet/in.h> | |
#include <netinet/ip.h> | |
#include <netinet/tcp.h> | |
#include <arpa/inet.h> | |
#include <errno.h> | |
#include <poll.h> | |
#include <sys/epoll.h> | |
#include <sys/ioctl.h> | |
#define SRC_PORT 54321 | |
#define DST_PORT 111 | |
#define SRC_HOST "10.10.0.3" | |
#define DST_HOST "10.10.0.2" | |
static int counter = 0; | |
struct pseudo_ip_header { | |
unsigned int src_ip; | |
unsigned int dst_ip; | |
unsigned char zero; | |
unsigned char protocol; | |
unsigned short len; | |
}; | |
struct pseudo_header { | |
struct pseudo_ip_header iphdr; | |
struct tcphdr ptcphdr; | |
}; | |
static unsigned short checksum(unsigned short *buffer, int size) | |
{ | |
unsigned long cksum = 0; | |
while (size > 1) { | |
cksum += *buffer++; | |
size -= sizeof(unsigned short); | |
} | |
if (size) | |
cksum += *(char *)buffer; | |
cksum = (cksum >> 16) + (cksum & 0xffff); | |
cksum += (cksum >> 16); | |
return (unsigned short)(~cksum); | |
} | |
static void check_port_raw_socket(int max) | |
{ | |
int src_port = SRC_PORT; | |
int dst_port = DST_PORT; | |
char srcip[] = SRC_HOST; | |
char dstip[] = DST_HOST; | |
struct tcphdr tcphdr; | |
struct pseudo_header pheader; | |
struct sockaddr_in peer; | |
struct sockaddr *peer_ptr; | |
int sock; | |
int saddr_size; | |
int windowsize = 4321; | |
int tcphdr_size = sizeof(struct tcphdr); | |
int iphdr_size = sizeof(struct ip); | |
printf("bench type: %s bench num: %d\n", __func__, max); | |
tcphdr.source = htons(src_port); | |
tcphdr.dest = htons(dst_port); | |
tcphdr.window = htons(windowsize); | |
tcphdr.seq = 1; | |
tcphdr.fin = 0; | |
tcphdr.syn = 1; | |
tcphdr.doff = 5; | |
tcphdr.rst = 0; | |
tcphdr.urg = 0; | |
tcphdr.urg_ptr = 0; | |
tcphdr.psh = 0; | |
tcphdr.ack_seq = 0; | |
tcphdr.ack = 0; | |
tcphdr.check = 0; | |
tcphdr.res1 = 0; | |
tcphdr.res2 = 0; | |
inet_aton(srcip, (struct in_addr *)&pheader.iphdr.src_ip); | |
inet_aton(dstip, (struct in_addr *)&pheader.iphdr.dst_ip); | |
pheader.iphdr.zero = 0; | |
pheader.iphdr.protocol = 6; | |
pheader.iphdr.len = htons(sizeof(struct ip)); | |
inet_aton(dstip, &peer.sin_addr); | |
peer.sin_port = htons(dst_port); | |
peer.sin_family = AF_INET; | |
saddr_size = sizeof(peer); | |
peer_ptr = (struct sockaddr *)&peer; | |
bcopy((char *)&tcphdr, (char *)&pheader.ptcphdr, sizeof(struct ip)); | |
tcphdr.check = checksum((unsigned short *)&pheader, 32); | |
counter = 0; | |
while (counter < max) { | |
sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP); | |
sendto(sock, &tcphdr, tcphdr_size, 0, peer_ptr, saddr_size); | |
while (1) { | |
struct tcphdr *tcp; | |
unsigned char buffer[4096] = {0}; | |
recvfrom(sock, buffer, 4096, 0, peer_ptr, &saddr_size); | |
tcp = (struct tcphdr *)(buffer + iphdr_size); | |
if (tcp->syn == 1 && tcp->ack == 1) { | |
counter++; | |
break; | |
} | |
} | |
close(sock); | |
} | |
} | |
static void check_port_sysconnect_so_linger(int max) | |
{ | |
int src_port = SRC_PORT; | |
int dst_port = DST_PORT; | |
char srcip[] = SRC_HOST; | |
char dstip[] = DST_HOST; | |
struct linger so_linger; | |
struct sockaddr_in peer; | |
struct sockaddr *peer_ptr; | |
int sock, peer_size; | |
int so_linger_size = sizeof(so_linger); | |
printf("bench type: %s bench num: %d\n", __func__, max); | |
so_linger.l_onoff = 1; | |
so_linger.l_linger = 0; | |
inet_aton(dstip, &peer.sin_addr); | |
peer.sin_port = htons(dst_port); | |
peer.sin_family = AF_INET; | |
peer_size = sizeof(peer); | |
peer_ptr = (struct sockaddr *)&peer; | |
counter = 0; | |
while (counter < max) { | |
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |
if (connect(sock, peer_ptr, peer_size) != -1) { | |
counter++; | |
} | |
setsockopt(sock, SOL_SOCKET, SO_LINGER, &so_linger, so_linger_size); | |
close(sock); | |
} | |
} | |
static void check_port_sysconnect_so_linger_poll(int max) | |
{ | |
int src_port = SRC_PORT; | |
int dst_port = DST_PORT; | |
char srcip[] = SRC_HOST; | |
char dstip[] = DST_HOST; | |
struct linger so_linger; | |
struct sockaddr_in peer; | |
struct sockaddr *peer_ptr; | |
int sock, peer_size; | |
int so_linger_size = sizeof(so_linger); | |
int opt = 1; | |
struct pollfd pfds[1]; | |
printf("bench type: %s bench num: %d\n", __func__, max); | |
so_linger.l_onoff = 1; | |
so_linger.l_linger = 0; | |
inet_aton(dstip, &peer.sin_addr); | |
peer.sin_port = htons(dst_port); | |
peer.sin_family = AF_INET; | |
peer_size = sizeof(peer); | |
peer_ptr = (struct sockaddr *)&peer; | |
pfds[0].events = POLLIN | POLLOUT; | |
counter = 0; | |
while (counter < max) { | |
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |
ioctl(sock, FIONBIO, &opt); | |
connect(sock, peer_ptr, peer_size); | |
setsockopt(sock, SOL_SOCKET, SO_LINGER, &so_linger, so_linger_size); | |
pfds[0].fd = sock; | |
if (poll(pfds, 1, -1) > 0) { | |
counter++; | |
} | |
close(sock); | |
} | |
} | |
static void check_port_sysconnect_so_linger_epoll(int max) | |
{ | |
int src_port = SRC_PORT; | |
int dst_port = DST_PORT; | |
char srcip[] = SRC_HOST; | |
char dstip[] = DST_HOST; | |
struct linger so_linger; | |
struct sockaddr_in peer; | |
struct sockaddr *peer_ptr; | |
int sock, peer_size; | |
int so_linger_size = sizeof(so_linger); | |
int opt = 1; | |
int epfd; | |
struct epoll_event ev, events[1]; | |
printf("bench type: %s bench num: %d\n", __func__, max); | |
so_linger.l_onoff = 1; | |
so_linger.l_linger = 0; | |
inet_aton(dstip, &peer.sin_addr); | |
peer.sin_port = htons(dst_port); | |
peer.sin_family = AF_INET; | |
peer_size = sizeof(peer); | |
peer_ptr = (struct sockaddr *)&peer; | |
epfd = epoll_create(1); | |
ev.events = EPOLLIN | EPOLLOUT; | |
counter = 0; | |
while (counter < max) { | |
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |
ioctl(sock, FIONBIO, &opt); | |
connect(sock, peer_ptr, peer_size); | |
setsockopt(sock, SOL_SOCKET, SO_LINGER, &so_linger, so_linger_size); | |
epoll_ctl(epfd, EPOLL_CTL_ADD, sock, &ev); | |
if (epoll_wait(epfd, events, 1, -1) > 0) { | |
counter++; | |
} | |
close(sock); | |
} | |
} | |
static void check_port_sysconnect(int max) | |
{ | |
int src_port = SRC_PORT; | |
int dst_port = DST_PORT; | |
char srcip[] = SRC_HOST; | |
char dstip[] = DST_HOST; | |
struct sockaddr_in peer; | |
struct sockaddr *peer_ptr; | |
int sock, peer_size; | |
printf("bench type: %s bench num: %d\n", __func__, max); | |
inet_aton(dstip, &peer.sin_addr); | |
peer.sin_port = htons(dst_port); | |
peer.sin_family = AF_INET; | |
peer_size = sizeof(peer); | |
peer_ptr = (struct sockaddr *)&peer; | |
counter = 0; | |
while (counter < max) { | |
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |
if (connect(sock, peer_ptr, peer_size) != -1) { | |
counter++; | |
} | |
close(sock); | |
} | |
} | |
int main(int argc, const char **argv) | |
{ | |
int max; | |
if (argc != 3) { | |
printf("type('raw' or 'connect') check_num\n"); | |
return 1; | |
} | |
max = atoi(argv[2]); | |
if (strcmp(argv[1], "raw") == 0) { | |
check_port_raw_socket(max); | |
} | |
if (strcmp(argv[1], "connect") == 0) { | |
check_port_sysconnect(max); | |
} | |
if (strcmp(argv[1], "so_linger_connect") == 0) { | |
check_port_sysconnect_so_linger(max); | |
} | |
if (strcmp(argv[1], "so_linger_connect_poll") == 0) { | |
check_port_sysconnect_so_linger_poll(max); | |
} | |
if (strcmp(argv[1], "so_linger_connect_epoll") == 0) { | |
check_port_sysconnect_so_linger_epoll(max); | |
} | |
return 0; | |
} |
あ、raw socket のやつだけ試行回数が一桁少ない...
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
raw socket
connect + SO_LINGER
non blocking connect + SO_LINGER + poll
non blocking connect + SO_LINGER + epoll