C++ Winsock2 sending integers with byte order - c++

I have been looking for a way to have an integer sent over a Windows Socket using Winsock2. I have looked at most, if not all, of the questions people have asked on stackoverflow already.
This is what I have for the client, that sends the integer:
struct struct_var
{
int Packet;
int Number;
};
struct_var *arraystruct;
arraystruct = (struct_var *) malloc(sizeof(struct_var));
(*arraystruct).Packet = 100;
(*arraystruct).Number = 150;
int bytes = send(client,(char*)arraystruct,sizeof(*arraystruct),0);`
I have also tried to send using:
int int_data = 4;
int bytes = send(server, (char*) &int_data, sizeof(int), 0);`
This was recommended on another stackoverflow question
This is the receiving side, which was also recommended:
int int_data;
int bytes = recv(server, (char*) &int_data, sizeof(int), 0);
cout << int_data;`
When I run these the output I get from command line is: -858993460
Does anyone know why this is happening?
I would also like it to have the correct byte order as this will be sent over multiple kinds of computers.
Thanks in advance who can help me out
Full Server Code:
int main() {
WSADATA wsaData;
WORD version;
int error;
version = MAKEWORD(2, 0);
error = WSAStartup(version, &wsaData);
if ( error != 0 )
{
return FALSE;
}
if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 0 )
{
WSACleanup();
return FALSE;
}
SOCKET server;
server = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(5555);
if (bind( server, (SOCKADDR*)&sin, sizeof(sin) ) == SOCKET_ERROR ){
DWORD ec=WSAGetLastError();
cerr << hex << "bind ERROR" << ec << endl;
return FALSE;
}
if ( listen( server, SOMAXCONN ) == SOCKET_ERROR ) {
DWORD ec=WSAGetLastError();
cerr << hex << "listen ERROR" << ec << endl;
return FALSE;
}
SOCKET client;
int length;
while(1) {
if ( listen( server, SOMAXCONN ) == SOCKET_ERROR ) {
DWORD ec=WSAGetLastError();
cerr << hex << "listen ERROR" << ec << endl;
return FALSE;
}
length = sizeof sin;
client = accept( server, (SOCKADDR*)&sin, &length );
cout << "Client connected" << endl;
cout << "Sending Instructions..." << endl;
int int_data;
int bytes;
bytes = recv(client, (char*) &int_data, sizeof(int), 0);
cout << int_data << endl;
}
}
}
Full Client Code:
int main() {
WSADATA wsaData;
WORD version;
int error;
version = MAKEWORD(2, 0);
error = WSAStartup(version, &wsaData);
if ( error != 0 )
{
return FALSE;
}
if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 0 )
{
WSACleanup();
return FALSE;
}
SOCKET client;
client = socket( AF_INET, SOCK_STREAM, 0 );
sockaddr_in sin;
memset( &sin, 0, sizeof sin );
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = inet_addr("127.0.0.1");
sin.sin_port = htons(5555);
if ( connect(client, (SOCKADDR*)(&sin), sizeof sin ) == SOCKET_ERROR ){
return FALSE;
}
int int_data = 4;
int bytes = send(client, (char*) &int_data, sizeof(int), 0);
}

Here's the problem:
int bytes = recv(server, (char*) &int_data, sizeof(int), 0);
Should be:
int bytes = recv(client, (char*) &int_data, sizeof(int), MSG_WAITALL);
A few other nitpicky things, that aren't causing your problem, but you should know:
Don't bind your server socket to 10.0.0.5. Bind to 0 (INADDR_ANY). That way, your code still works when you run it on machine who's IP addrss is 10.0.0.6.
Use htonl(), htons(), ntohs(), and ntohl() for interoperating with big-endian boxes.
Always check the return values from socket calls. If recv returns 0 or -1, it means the remote side has disconnected. (0 technically means the client has stopped sending, but unless you are doing shutdown half-close stuff, it means he disconnected).
TCP sockets are not message oriented, they are stream oriented. That is, just because you tell recv() to get N bytes, doesn't mean it will return N bytes. IP fragmentation, TCP segmentations, and other factors can make recv() return partial data. Use the MSG_WAITALL flag as appropriate.

You're making this almost impossible on yourself. Instead of starting with code, start with a protocol specification. You can look at the specifications of existing protocols that use TCP, such as HTTP, IMAP, and so on, to see what a protocol specification should include.
The protocol specification should explain everything that is sent or received at the byte level. It should explain how connections are established and torn down. It should explain how dead connections are detected from either end. If the protocol has application-layer messages, it should explain how they are delimited and how the receiver finds the ends of messages. It should specify who transmits when.
Then, debugging is easy. Follow this flowchart:
1) Does the server follow the specification? If not, the server is broken.
2) Does the client follow the specification? If not, the client is broken.
3) If it still doesn't work, the specification is broken.
This makes it possible to ensure that the server and client work together. And when they don't, it makes it possible to know which side needs to be fixed.
It only take an hour or two to sketch out a protocol specification, and I promise you the time saved will be more than worth it. All it takes is one time you change the wrong end when something doesn't work (and then find lots of things are newly-broken because you fixed one of the places that was right) to pay for the time taken. Plus, as a bonus, it is then possible to make other implementations.

I was stuck at this problem as well and I noticed that my client wasn't even connecting.
Try to save the value returned by connect() and recv() making sure its > -1 or print out some error.

Related

Recvfrom function not receiving data

This is my first time posting so hopefully I'm doing it right. I've been browsing the site trying to find an answer to this problem, but I'm at a loss.
I developed some UDP code in C++ in Linux on a Raspberry Pi, that's supposed to receive from something on Windows. If it matters, I'm using Remote Desktop to access the Pi from the same computer the code is on. Due to other problems, I can't simply put this code on the Pi.
I can create a socket, bind() it, and do everything up to the point where the recvfrom() function is supposed to grab the data. At this point, it simply stops working. There's no error, it just won't display anything below it, even an if statement for if recvfrom is -1.
I've tried making it blocking and non-blocking, changing the variable names, and plopping this part of the code down in its own separate file to debug, but it still won't receive anything. I know the server code works fine.
This isn't my first time working with UDP, but I'm also not super experienced, and I don't know what could be causing this issue. There's another UDP function in the code that works.
Why aren't I receiving data, and how can I fix it?
int PORT = 20016;
struct sockaddr_in serverAddress;
memset((char *) &serverAddress, 0, sizeof(serverAddress));
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(PORT);
serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
int packetSize = 36;
char packetData[packetSize];
struct sockaddr_in clientAddress;
socklen_t caddr_length= sizeof clientAddress;
handle = socket( AF_INET, SOCK_DGRAM, 0 );
if(handle < 0)
{
perror("socket\n");
exit;
}
if ( bind( handle, (struct sockaddr*)&serverAddress, sizeof(serverAddress) ) < 0 )
{
perror("bind failure\n");
exit;
}
while ( 1 )
{
cout << "receiving data..." << endl;
int received_bytes = recvfrom(handle, packetData, sizeof(packetData),0, (struct sockaddr*)&clientAddress, &caddr_length);
if ( received_bytes == -1)
{
cout << "Data not received: " << strerror(errno) << endl;
}
else
{
cout << "Data incoming:" << endl;
int *dataPacket=(int *)packetData;
a = dataPacket[0];
b = dataPacket[1];
c = dataPacket[2];
d = dataPacket[3];
e = dataPacket[4];
f = dataPacket[5];
g = dataPacket[6];
h = dataPacket[7];
i = dataPacket[8];
}
}
return 0;
}

WinSock2 client/server communication: send & receive strings

I am having a bit of difficulty trying to code this as I do not know a lot. I have a setup for two PCs that can communicate between each other. It works and all, but it only can send single characters to each other. One PC acts like a server if the command is executed with no IP address argument, and the other, given a server IP address, acts like a client to connect to the server.
The code is all here:
// Quick and dirty - error checks omitted for brevity.
#include <iostream>
#include <string>
#include <conio.h>
#include <WinSock2.h>
#include <ws2tcpip.h>
using namespace std;
void chat (int socket_d)
{
while (true)
{
if (_kbhit ())
{
char ch;
ch = _getche();
int n;
n = send (socket_d, &ch, 1, 0);
if (ch == '\r')
{
cout << "\n";
}
}
int n;
int count = 0;
char byte; // Read one byte at a time - is this efficient?
n = recv (socket_d, &byte, 1, 0);
if (n <= 0)
{
if (WSAGetLastError() != WSAEWOULDBLOCK) // A real problem - not just avoiding blocking.
{
cout << "Terminated " << WSAGetLastError() << "\n";
return;
}
}
else
{
cout << (char)byte;
if ((char) byte == '\r')
cout << "\n";
}
}
}
int main (int argc, char * argv [])
{
// Messy process with windows networking - "start" the networking API.
WSADATA wsaData;
int result = WSAStartup (MAKEWORD (2, 2), &wsaData);
unsigned short port = 25565;
// If argument is IP address - be a client and connect to it. Otherwise
// be a server.
if (argc > 1)
{
int socket_d;
socket_d = socket (AF_INET, SOCK_STREAM, 0);
// be a client.
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr (argv[1]); // Parse the string and create the 32 bit address.
server_addr.sin_port = htons (port); // Watch out for the endian conversion!
connect (socket_d, (sockaddr *) &server_addr, sizeof (server_addr));
u_long iMode=1;
ioctlsocket (socket_d, FIONBIO, &iMode); // put the socket into non-blocking mode.
chat (socket_d);
closesocket (socket_d);
}
else
{
// be a server
int listen_socket_d;
int connection_socket_d;
listen_socket_d = socket (AF_INET, SOCK_STREAM, 0);
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY; // A placeholder that will be replaced with my own address.
server_addr.sin_port = htons (port); // Watch out for the endian conversion!
bind (listen_socket_d, (struct sockaddr *) &server_addr, sizeof (server_addr));
int backlog = 5;
listen (listen_socket_d, backlog);
// take only the first connection.
struct sockaddr_storage their_addr;
int their_addr_size = sizeof(their_addr);
connection_socket_d = accept (listen_socket_d, (struct sockaddr *) &their_addr, &their_addr_size);
u_long iMode=1;
ioctlsocket (connection_socket_d, FIONBIO, &iMode); // put the socket into non-blocking mode.
chat (connection_socket_d);
closesocket (connection_socket_d);
}
return 0;
}
What I am trying to achieve is to be able to send strings instead of single characters. The way I would like this to work is by increasing the byte size it sends instead of single byte currently. The way I am assuming it could work, let's say a total size of 64 bytes is sent and received at a time.
It's not really clear from this where your problem area is actually.
My solution is below. The basic idea is to allocate send and receive buffers of equal size, append characters to the send buffer on keyboard input, and transfer the buffer when it is full or the user hits the return key.
The non-blocking send function might not send the whole buffer at once (see the docs). I decided to go ahead and block here until the entire buffer was sent so I didn't have to track separate input and transmit buffers. You could improve on this, I'm sure.
The receive part just echoes whatever bytes have been received. In general, there's no way to know whether the other user was "done" sending data, so we just print what we received after the first call to recv.
I always memset the buffers to all zeros after each send and receive to prevent weird behavior from missing null terminators. It would be more optimized to simply append a null character to the end of the current string, but I get paranoid sometimes.
Here's my code:
#define BUFFER_SIZE 64
void chat (int socket_d)
{
char sendBuffer[BUFFER_SIZE] = { 0 };
char receiveBuffer[BUFFER_SIZE] = { 0 };
int bufferPosition = 0;
int charsSent = 0;
int charsReceived = 0;
while (true)
{
if (_kbhit ())
{
sendBuffer[bufferPosition++] = _getche();
if (sendBuffer[bufferPosition - 1] == '\r' || bufferPosition == BUFFER_SIZE - 1)
{
// This defeats the purpose of a non-blocking socket, I know.
// You can do better by keeping separate buffers for sending and
// collecting input.
while (charsSent < bufferPosition)
{
charsSent += send(
socket_d,
&sendBuffer[charsSent], // Treats the address of a character as a string.
bufferPosition - charsSent, // Only send the part that hasn't been sent yet.
0);
}
memset(sendBuffer, 0, bufferPosition); // Paranoid.
bufferPosition = charsSent = 0;
cout << "\n";
}
}
charsReceived = recv (socket_d, receiveBuffer, BUFFER_SIZE, 0);
if (charsReceived <= 0)
{
if (WSAGetLastError() != WSAEWOULDBLOCK) // A real problem - not just avoiding blocking.
{
cout << "Terminated " << WSAGetLastError() << "\n";
return;
}
}
else
{
cout << receiveBuffer;
if (receiveBuffer[charsReceived - 1] == '\r')
cout << "\n";
memset(receiveBuffer, 0, charsReceived); // Super paranoid.
}
}
}
Now, I wouldn't really consider this "good" until it supports UTF-8, or at least wchar_t. ASCII lacks a lot of characters that people expect to be able to use in a real chat application.
PS - According to Visual Studio 2013, the inet_addr function is deprecated. I used inet_ptons instead. Here's the documentation on the Winsock implementation for it.

Nonblocking sockets even if not explicitly setting them as nonblocking

I have a TCP application written in C++, where a client and a server exchange data. I've istantiated a socket, believing that it would have been blocking by default; on the contrary, after server waits for a client, I have that client calls the recv function without waiting for data. This is the code in which I inizialize the socket fr the client.
int TCPreceiver::initialize(char* address, int port)
{
sock = socket (AF_INET, SOCK_STREAM, 0);
cout << "Socket: " << sock << endl;
sockaddr_in target;
target.sin_family = AF_INET;
target.sin_port = htons (port);
target.sin_addr.s_addr = inet_addr(address);
int fails=0;
while (connect(sock, (sockaddr*) &target, sizeof(target)) == -1)
{
fails++;
if (fails==10)
{
close(sock);
cout << "Error with connection to the server, try again"<< endl;
exit(-1);
}
}
cout << "Client connected (control channel)" << endl;
unsigned char text[10]; //Request message
//fill text[]
if(send(sock, (char*)text, 10, 0)==-1)
{
printf("send() failed with error code : %d" , -1);
exit(EXIT_FAILURE);
}
return 0;
}
I've tried adding this code:
int opts;
opts = fcntl(sock,F_GETFL);
if (opts < 0) {
perror("fcntl(F_GETFL)");
exit(0);
}
opts = (opts & (~O_NONBLOCK));
if (fcntl(sock,F_SETFL,opts) < 0) {
perror("fcntl(F_SETFL)");
exit(0);
}
but it still doesn't work, and if I call the recv(), the application doesn't block (and recv() always returns 0). Here is the function where I call the recv():
void TCPreceiver::receive(char* text, int& dim)
{
int ret;
ret = recv(sock, text, dim, 0);
dim=ret;
if(ret == -1){
printf("recv() failed with error (%d)\n", ret);
//system("PAUSE");
exit(1);
}
}
Where am I wrong?
recv() returning zero indicates either (1) you passed a zero length, which is just a programming error which I won't discuss further here, or (2) end of stream. The peer has close the connection. This isn't a non-blocking situation, this is the end of the connection. You must close the socket and stop using it. It will never return anything. It zero ever again.
See the man pages.

Why sending datagram doesn't work if I don't create a TCP connection first?

The following c++ program should convert each line to uppercase using socket datagram to communicate between two threads.
Example:
Hello World!<return>
HELLO WORLD!
123abc!<return>
123ABC!
<return>
<end program>
The program as written works for me, however if I comment the bugfix() function call in the main the program wait indefinitely after the first line of input.
Example:
Hello World!<return>
<the program wait indefinitely>
This happen on windows 7 with the last update as 10/04/2011 using the last MinGW32.
#include <iostream>
#include <cstdlib>
#include <cctype>
#include <sys/types.h>
#include <winsock.h>
#include <windows.h>
#include <process.h>
using namespace std;
#define CHECK(exp, cond) do { typeof(exp) _check_value_ = exp; check(_check_value_ cond, _check_value_, __LINE__, #exp #cond); } while(0)
template <class T>
void check(bool ok, T value, int line, const char* text) {
if (!ok) {
cerr << "ERROR(" << line << "):" << text << "\nReturned: " << value << endl;
cerr << "errno=" << errno << endl;
cerr << "WSAGetLastError()=" << WSAGetLastError() << endl;
exit(EXIT_FAILURE);
}
}
#define DATA_CAPACITY 1000
#define PORT 23584
#define TEST_IP "192.0.32.10"
#define MYSELF "127.0.0.1"
#define DST_IP MYSELF
sockaddr_in address(u_long ip, u_short port) {
sockaddr_in addr = { };
addr.sin_family = AF_INET;
addr.sin_port = port;
addr.sin_addr.s_addr = ip;
return addr;
}
void __cdecl client_thread(void* args) {
SOCKET s = *(SOCKET*)args;
sockaddr_in addr = address(inet_addr(DST_IP), htons(PORT));
char data[DATA_CAPACITY];
while (1) {
cin.getline(data, DATA_CAPACITY);
int data_len = strlen(data);
CHECK(sendto(s, data, data_len, 0, (sockaddr*)&addr, sizeof addr), >= 0);
CHECK(recvfrom(s, data, DATA_CAPACITY, 0, NULL, NULL), >= 0);
cout << data << endl;
if (data_len == 0)
break;
}
CHECK(closesocket(s), == 0);
}
void __cdecl server_thread(void* args) {
SOCKET s = *(SOCKET*)args;
sockaddr_in addr = address(INADDR_ANY, htons(PORT));
int addr_size = sizeof addr;
CHECK(bind(s, (sockaddr*)&addr, sizeof addr), != SOCKET_ERROR);
char data[DATA_CAPACITY];
while (1) {
int data_len = recvfrom(s, data, DATA_CAPACITY, 0, (sockaddr*)&addr, &addr_size);
CHECK(data_len, >= 0);
for (int i = 0; i < data_len; i++)
if (islower(data[i]))
data[i] = toupper(data[i]);
CHECK(sendto(s, data, data_len, 0, (sockaddr*)&addr, addr_size), >= 0);
if (data_len == 0)
break;
}
CHECK(closesocket(s), == 0);
}
// This function create a TCP connection with www.example.com and the close it
void bugfix() {
SOCKET s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
sockaddr_in addr = address(inet_addr(TEST_IP), htons(80));
connect(s, (sockaddr*)&addr, sizeof addr);
CHECK(closesocket(s), == 0);
}
int main()
{
cout << "Convert text to uppercase, an empty line terminate the program" << endl;
WSADATA wsaData;
CHECK(WSAStartup(MAKEWORD(2, 2), &wsaData), == 0);
SOCKET client = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
SOCKET server = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
CHECK(client, != INVALID_SOCKET);
CHECK(server, != INVALID_SOCKET);
// if this function is not called the program doesn't work
bugfix();
HANDLE hClient = (HANDLE)_beginthread(client_thread, 0, &client);
HANDLE hServer = (HANDLE)_beginthread(server_thread, 0, &server);
HANDLE h[] = { hClient, hServer };
WaitForMultipleObjects(sizeof h / sizeof *h, h, TRUE, INFINITE);
CHECK(WSACleanup(), == 0);
return EXIT_SUCCESS;
}
int data_len = strlen(data);
Tony Hoare called his definition of a NULL pointer his billion dollar mistake. Having strings zero-terminated must be Dennnis Ritchie's ten billion dollar mistake. Add one.
Your program is otherwise an elaborate way to discover that UDP is not a reliable protocol. The network stack is allowed to arbitrarily make UDP packets disappear or reorder them. Which is okay as long as there's another protocol on top of it that detects this, like TCP. You are flying without such bandaids, bugfix() is not actually a workaround.
Use TCP, send the packet length first so that the receiver will know how many bytes are following so you're immune to stream behavior. But more to the point, exchanging data between threads through a socket is a really expensive way to avoid using an array with a mutex. Threads have unfettered access to memory in the process, you don't need an interprocess communication mechanism to get them to exchange data.
I see several problems right off the bat.
I normally don't use IPPROTO_UDP flag to create the socket. Just pass 0 for the protocol parameter to the socket.
SOCKET client = socket(PF_INET, SOCK_DGRAM, 0);
SOCKET server = socket(PF_INET, SOCK_DGRAM, 0);
More important. You need to call "bind" on the client socket in the same way that you do the server socket. If you want the OS to pick a randomly available port for you, you can use 0 as the port value and IPADDR_ANY for the IP address. If you want to know what the OS picked as a local port for you, you can use getsockname. Something like the following:
void __cdecl client_thread(void* args) {
SOCKET s = *(SOCKET*)args;
sockaddr_in addr = address(inet_addr(DST_IP), htons(PORT));
sockaddr_in localAddrBind = address(INADDR_ANY, 0);
sockaddr_in localAddrActual = {};
int length = sizeof(localAddrActual);
int bindRet = bind(s, (sockaddr*)&localAddrBind, sizeof(localAddrBind));
getsockname(s, (sockaddr*)&localAddrActual, &length);
printf("Listening on port %d\n", ntohs(localAddrActual.sin_port));

Problem with simple UDP client/server application

Ok. So I have a simple client program sending images over UDP to a specified IP address. At the specified IP a server program is listening and should receive the images.
When I try both programs on localhost (i.e. they are both running at 127.0.0.1) it works and the server receives the images. When I try to put the client and the server programs on different PCs in the same network it does not work.
147.232.24.163 is the server IP, 147.232.24.150 is the client IP.
Here is my client program:
// Initialize UDP.
struct sockaddr_in server;
int n_sent;
int socketId = socket(AF_INET, SOCK_DGRAM, 0);
if (socketId < 0)
{
cout << "Problem creating socket." << endl;
}
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr("147.232.24.163");
// Establish the server port number - we must use network byte order!
server.sin_port = htons(42001);
for ( int iter = 0; iter < 60; iter++ )
{
// load image into jpegBuf
n_sent = sendto(socketId, reinterpret_cast<char*> (&jpegBuf[0]), jpegBuf.size(), 0, (struct sockaddr*) &server, sizeof(server));
if (n_sent < 0) {
cout << "Problem sending data." << endl;
}
}
close(socketId);
Here is my server program:
int main()
{
int bufferSize = 1024000;
int iSockFd = -1;
int iLength = 0;
struct sockaddr_in servAddr, cliAddr;
char buff[bufferSize];
iSockFd=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
memset(&servAddr, 0, sizeof(servAddr));
memset(&cliAddr, 0, sizeof(cliAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = inet_addr("147.232.24.163");
servAddr.sin_port = htons(42001);
int cliAddrLen = sizeof(struct sockaddr_in);
int bindRet = bind(iSockFd, (struct sockaddr*)&servAddr, sizeof(servAddr));
cout << "Bind returned " << bindRet << endl;
int i = 0;
while (true)
{
int iRcvdBytes=recvfrom(iSockFd, buff, bufferSize, 0,
(struct sockaddr*)&cliAddr, (socklen_t*)&cliAddrLen);
if (0 == i % 5)
{
cout << "Received " << iRcvdBytes << " bytes from the client" << endl;
}
i++;
}
close(iSockFd);
return 0;
}
Any ideas why it does not work? I don't get any error messages.
This is not a solution but your code should be checking iRcvdbytes for error in the same way as the send code checks the result of sendto.
A return of 0 means the socket was closed gracefully (if connection-oriented - that should not apply here), SOCKET_ERROR means an error (in WinSock2 at least).
The socket on the send side needs to be created with IPPROTO_UDP, not 0. This could definitely be causing your failure.