simple socket, how much data should i sent?

Hello everyone!

I created this class long time ago in order to work with socket the way
more comfortable for me and the reason i am showing this class is i want to show
how i am doing everything.

Note: spchar is simple string like class what holds string related functions.
It's just an char * = new char[x], not dynamic container.

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
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282


#ifndef SPSOCKET_H
#define SPSOCKET_H
#pragma once

#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")

#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <Windows.h>
#include <stdio.h>
#include <tchar.h>
#include <SDKDDKVer.h>
#include <vector>
#include "spchar.h"

#define SPC_IP "127.0.0.1"

struct SPSOCKET
{
	bool alive = false;
	SOCKET socket = 0;
};

class spsock
{
public:
	vector<SPSOCKET> sockets;
	spchar *ip;
	spchar *port;
	spchar *error;
	int avcount;
	int index;
	SOCKET client;


	spsock()
	{
		port = 0;
		ip = new spchar(20);
		port = new spchar(20);
		error = new spchar(256);
		avcount = 0;
		index = 0;
		client = INVALID_SOCKET;
	}

	int sendmessage(int index, char *message, int size)
	{
		int r = send(sockets[index].socket, message, size, 0);
		if (r <= 0)
		{
			removeclient(index);
			return r;
		}
		return r;
	}

	int receivemessage(int index, char *message, int size)
	{
		int r = recv(sockets[index].socket, message, size, 0);
		if (r <= 0)
		{
			removeclient(index);
			return r;
		}
		return r;
	}

	void removeclient(int index)
	{
		closesocket(sockets[index].socket);
		sockets[index].alive = 0;
		sockets[index].socket = INVALID_SOCKET;
		avcount++;
	}

	int addclient(SOCKET client)
	{
		if (avcount > 0)
		{
			for (unsigned int a = 0; a < sockets.size(); a++)
			{
				if (!sockets[a].alive)
				{

					sockets[a].socket = client;
					sockets[a].alive = 1;
					avcount--;
					return a;
				}
			}
		}
		SPSOCKET s;
		s.alive = 1;
		s.socket = client;
		sockets.push_back(s);
		return sockets.size() - 1;
	}

	bool acceptclient()
	{
		client = accept(sockets[0].socket, NULL, NULL);

		if (client != INVALID_SOCKET)
		{
			char value = 1;
			// setsockopt(client, IPPROTO_TCP, TCP_NODELAY, &value, sizeof(value));
			SPSOCKET s;
			s.alive = 1;
			s.socket = client;
			sockets.push_back(s);
			return true;
		}

		return false;
	}

	bool createserver(spchar inip, spchar inport)
	{
		*ip = inip;
		*port = inport;
		WSADATA wsaData;
		if (!sockets.size())
		{
			SPSOCKET s;
			sockets.push_back(s);
		}
		client = INVALID_SOCKET;

		struct addrinfo *result = NULL;
		struct addrinfo hints;

		int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
		if (iResult != 0) {
			error->format("WSAStartup failed with error: %d\n", iResult);
			return false;
		}

		ZeroMemory(&hints, sizeof(hints));
		hints.ai_family = AF_INET;
		hints.ai_socktype = SOCK_STREAM;
		hints.ai_protocol = IPPROTO_TCP;
		hints.ai_flags = AI_PASSIVE;

		if (ip->size) iResult = getaddrinfo(ip->getchar(), port->getchar(), &hints, &result);
		else iResult = getaddrinfo(NULL, port->getchar(), &hints, &result);

		if (iResult != 0) {
			error->format("getaddrinfo failed with error: %d\n", iResult);
			WSACleanup();
			return false;
		}

		sockets[0].socket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);

		if (sockets[0].socket == INVALID_SOCKET) {
			error->format("socket failed with error: %ld\n", WSAGetLastError());
			freeaddrinfo(result);
			WSACleanup();
			return false;
		}

		// u_long iMode = 1;
		// iResult = ioctlsocket(sockets[0].socket, FIONBIO, &iMode);

		if (iResult == SOCKET_ERROR) {
			error->format("ioctlsocket failed with error: %d\n", WSAGetLastError());
			closesocket(sockets[0].socket);
			WSACleanup();
			return false;
		}

		iResult = bind(sockets[0].socket, result->ai_addr, (int)result->ai_addrlen);
		if (iResult == SOCKET_ERROR) {
			error->format("bind failed with error: %d\n", WSAGetLastError());
			freeaddrinfo(result);
			closesocket(sockets[0].socket);
			WSACleanup();
			return false;
		}

		freeaddrinfo(result);
		iResult = listen(sockets[0].socket, SOMAXCONN);

		if (iResult == SOCKET_ERROR) {
			error->format("listen failed with error: %d\n", WSAGetLastError());
			closesocket(sockets[0].socket);
			WSACleanup();
			return false;
		}
		return true;
	}

	bool createclient(spchar inip, spchar inport)
	{
		if (!sockets.size())
		{
			SPSOCKET s;
			sockets.push_back(s);
		}
		*ip = inip;
		*port = inport;
		WSADATA wsaData;
		struct addrinfo *result = NULL, *ptr = NULL, hints;
		int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);

		if (iResult != 0) {
			error->format("WSAStartup failed with error: %d\n", iResult);
			return false;
		}

		ZeroMemory(&hints, sizeof(hints));
		hints.ai_family = AF_UNSPEC;
		hints.ai_socktype = SOCK_STREAM;
		hints.ai_protocol = IPPROTO_TCP;
		iResult = getaddrinfo(ip->getchar(), port->getchar(), &hints, &result);

		if (iResult != 0)
		{
			error->format("getaddrinfo failed with error: %d\n", iResult);
			WSACleanup();
			return false;
		}

		for (ptr = result; ptr != NULL; ptr = ptr->ai_next) 
		{
			sockets[0].socket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);

			if (sockets[0].socket == INVALID_SOCKET) {
				error->format("socket failed with error: %ld\n", WSAGetLastError());
				WSACleanup();
				return false;
			}

			iResult = connect(sockets[0].socket, ptr->ai_addr, (int)ptr->ai_addrlen);

			if (iResult == SOCKET_ERROR)
			{
				closesocket(sockets[0].socket);
				sockets[0].socket = INVALID_SOCKET;
				error->format("The server is down... did not connect");
			}
		}

		freeaddrinfo(result);

		if (sockets[0].socket == INVALID_SOCKET)
		{
			error->format("Unable to connect to server!\n");
			WSACleanup();
			return false;
		}

		// u_long iMode = 1;
		// iResult = ioctlsocket(sockets[0].socket, FIONBIO, &iMode);
		if (iResult == SOCKET_ERROR)
		{
			error->format("ioctlsocket failed with error: %d\n", WSAGetLastError());
			closesocket(sockets[0].socket);
			WSACleanup();
			return false;
		}

		char value = 1;
		// setsockopt(sockets[0].socket, IPPROTO_TCP, TCP_NODELAY, &value, sizeof(value));
		return true;
	}

	~spsock()
	{


	}
};


#endif 


Those who understand sockets know now how everything is and now the question.

If i have really large amount of data what size is unknown, it can be large it can be small or it can be huge.

If the data is huge, would it be safe if i send the whole data or should i cut it into smaller pieces?

If i should not send the whole data then what is the safe size of what i can send?


I am beginner at working with socket, to be honest all i did was 2 programs, one server and one client and client sending message to server and server back to client. Simple cmd program where you can type the message, nothing fancy.
Last edited on
If the files have an acceptable size (Nowadays i'd say, up to 512mb are okay), for as long as you use TCP, it really doesn't matter since the packet will be split up properly from the system.

Otherwise, please consider that your file needs to be stored in RAM twice for it to be correctly sent. For a 4GB file, you'd need more than 8GB of RAM, and you have to hope the RAM's not fragmented in that moment.

For sending huge data, the best method would be:

1. Open a file and start a for loop.
2. Read a good chunk of the file (something like 32MB should be good).
3. Send this tiny chunk in blocking-mode. This will wait for the chunk to be completely sent, and we'll be left with very low possibilities for out-of-memory errors.

This method however is only optimal for SSDs since they can read data much faster.

Please consider a theorical USB drive with a 10MB/s read speed and a 8MBit/s internet connection for the following:
The USB drive takes 3.2 seconds to read 32MB of data. Network is not being used.
Network takes 32 seconds to send 32MB of data. USB is not being used.
The USB drive takes 3.2 more seconds to read 32MB of data. Network is not being used.

As you should see, the USB drive is not being used while you send data through the internet, and while you use the USB drive, the internet connection is not being used.

Another approach to this would be: having extra threads (one for networking, one for reading data) properly synced up to use resources as soon as they are available.

In the above example, you can save up to 3.2 seconds every 32MB.
For a 1GB file, that would be 1"40'.


TLDR: Do not send the file all at once. Read chunk 1, send chunk 1, read chunk 2, send chunk 2...
Last edited on
Topic archived. No new replies allowed.