View difference between Paste ID: MzP93aAC and T6N7hQky
SHOW: | | - or go back to the newest paste.
1
#include <cstdio>
2
#include <cstdlib>
3
4
#include <unistd.h>
5
#include <errno.h>
6
7
#include <sys/types.h>
8
#include <sys/socket.h>
9
#include <netinet/in.h>
10
11
#include <netdb.h>
12
#include <arpa/inet.h>
13
14
int create_socket(bool server = false)
15
{
16
	addrinfo  hints = {};
17
	addrinfo* servinfo;
18
19
	int sockfd = -1;
20
	int rv;
21
22
	hints.ai_family   = AF_INET;
23
	hints.ai_socktype = SOCK_STREAM;
24
	hints.ai_flags    = server ? AI_PASSIVE : 0;
25
26
	if ((rv = getaddrinfo(server ? 0 : "localhost", "12345", &hints, &servinfo)))
27
	{
28
		printf("getaddrinfo failed: %s\n", gai_strerror(rv));
29
		exit(1);
30
	}
31
32
	for(auto p = servinfo; p; p = p->ai_next)
33
	{
34
		if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
35
		{
36
			perror("socket");
37
			continue;
38
		}
39
40
		if(server)
41
		{
42
			int yes = 1;
43
			setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
44
45
			if(bind(sockfd, p->ai_addr, p->ai_addrlen) == -1)
46
			{
47
				close(sockfd);
48
				perror("bind");
49
				continue;
50
			}
51
		}
52
		else
53
		{
54
			if(connect(sockfd, p->ai_addr, p->ai_addrlen) == -1)
55
			{
56
				close(sockfd);
57
				perror("connect");
58
				continue;
59
			}
60
			else
61
				puts("client: connected");
62
		}
63
64
		break;
65
	}
66
67
	freeaddrinfo(servinfo);
68
	return sockfd;
69
}
70
71
void server()
72
{
73
	int socket = create_socket(true);
74
	if(listen(socket, 5) == -1)
75
	{
76
		perror("listen");
77
		exit(1);
78
	}
79
	puts("server: listening");
80
81
	int conn = -1;
82
	sockaddr_storage addr;
83
	unsigned int sizeof_addr = sizeof(addr);
84
85
	for(;;)
86
	{
87
		if((conn = accept(socket, (sockaddr *) &addr, &sizeof_addr)) == -1)
88
		{
89
			perror("accept");
90
		}
91
		else
92
		{
93
			puts("server: accept");
94
95
			if(!fork()) // actually not necessary, only got 1 client
96
			{
97
				close(socket);
98
				char *buf = new char[1024*1024];
99
				for(;;) read(conn, buf, 1024*1024); // black hole
100
			}
101
		}
102
	}
103
}
104
105
void do_send(int socket, const char* buf, unsigned int size/*,  bool nonblock = false */)
106
{
107
	unsigned int sent = 0;
108
	unsigned int count = 0;
109
110
	while(sent < size)
111
	{
112
//      int n = send(socket, &buf[sent], size - sent, nonblock ? MSG_DONTWAIT : 0);
113
		int n = send(socket, &buf[sent], size - sent, 0);
114
115
		if (n == -1)
116
		{
117
			if(errno == EAGAIN)
118
			{
119
				printf(".");
120
			}
121
			else
122
			{
123
				perror("\nsend");
124
				return;
125
			}
126
		}
127
		else
128
		{
129
			sent += n;
130
			printf("  --> sent a chunk of %u bytes (send no. %u, total sent = %u)\n", n, ++count, sent);
131
		}
132
	}
133
}
134
135
void client()
136
{
137
	const unsigned int max_size = 64*1024*1024; // sending up to 64MiB in one call
138
139
	sleep(1); // give server a second to start up
140
141
	int socket = create_socket();
142
143
144
	unsigned int send_buffer_size = 0;
145
	unsigned int len = sizeof(send_buffer_size);
146
147
	if(getsockopt(socket, SOL_SOCKET, SO_SNDBUF, &send_buffer_size, &len))
148
		perror("getsockopt");
149
150
	// Linux internally doubles the buffer size, and getsockopt reports the doubled size
151
	printf("send buffer size = %u  (doubled, actually %u)\n", send_buffer_size, send_buffer_size/2);
152
153
	if(socket == -1)
154
	{
155
		puts("no good");
156
		exit(1);
157
	}
158
159
	char *buf = new char[max_size]; // uninitialized contents, but who cares
160
161
	for(unsigned int size = 65536; size <= max_size; size += 16384)
162
	{
163
		printf("attempting to send %u bytes\n", size);
164
		do_send(socket, buf, size);
165
	}
166
	puts("all done");
167
	delete buf;
168
}
169
170
171
int main()
172
{
173
	if(fork() > 0) server(); else client();
174
	return 0;
175
}