Hi I am new in Socket Programming and try to create a client server applciation using in which my server is Camera and client in my C++ application.
When I see the packet transfer between computer and camera it showing that camera is sending more than 150000 packets after that it stops. But when I am receving that I am able to receive 400 - 450 packets at a time after that the recvfrom function goes to waiting state. and If I again run that exe file without stopping the previous one it again receive 400-450 packets.
Code for Receving Packets
SOCKET out1 = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
if (out1 == INVALID_SOCKET)
{
cout << out1 << endl;
}
server.sin_family = AF_INET;
server.sin_port = htons(3956);
inet_pton(AF_INET, "192.168.1.140", &server.sin_addr);
int serverLength = sizeof(server);
connect(out1, (sockaddr*)&server, serverLength);
while (1)
{
memset(buf, 0, sizeof(buf));
int bytesIn = recvfrom(out1, buf, 1444, 0, (sockaddr*)&server, &serverLength);
if (bytesIn > 0)
{
cout << "Image Received :" << bytesIn <<packet_counter << endl;
packet_counter++;
}
else
{
cout << "Not Received : " << endl;
}
}
I am running the .exe with the administrator rights.
So can anyone please tell me why the recvfrom function is going in waiting state.
Thanks in Advance.
EDIT:-
Sorry that I am providing the whole code.
#include <stdio.h>
#include <Windows.h>
#include <thread>
#include <WinSock2.h>
// Library
#pragma comment(lib, "ws2_32.lib")
using namespace std;
//***** Function Decleration *****//
void _packetConfig(SOCKET);
void _sendPacket(SOCKET, const char*, int, int);
// Global Variable
sockaddr_in server;
//***** Main Function *****//
void main(char argc, char* argv[])
{
WSADATA data;
WORD version = MAKEWORD(2, 2);
if(WSAStartup(version, &data) == SOCKET_ERROR)
{
cout << "Can't Start Socket" << WSAGetLastError<<endl;
return;
}
char buf[2000];
SOCKET out1 = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
if (out1 == INVALID_SOCKET)
{
cout << out1 << endl;
}
server.sin_family = AF_INET;
server.sin_port = htons(3956);
inet_pton(AF_INET, "192.168.1.140", &server.sin_addr);
int serverLength = sizeof(server);
connect(out1, (sockaddr*)&server, serverLength);
int packet_counter = 0;
SOCKET out = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
_packetConfig(out);
cout << "Inside Main" << endl;
while (1)
{
//connect(out1, (sockaddr*)&server, serverLength);
memset(buf, 0, sizeof(buf));
int bytesIn = recvfrom(out1, buf, 1444, 0, (sockaddr*)&server, &serverLength);
if (bytesIn > 0)
{
cout << "Image Received :" << bytesIn <<packet_counter << endl;
packet_counter++;
}
else
{
cout << "Not Received : " << endl;
}
}
WSACleanup();
}
//***** Function to Send Bytes to the Camera *****//
void _sendPacket(SOCKET sock, const char* s, int len, int i)
{
int sendOk = sendto(sock, (const char*)s, len, 0, (sockaddr*)&server, sizeof(server));
if (sendOk == SOCKET_ERROR)
{
cout << "Didn't Work" << WSAGetLastError() << endl;
}
else
{
cout << "\nSend Succesfully" << " " << i << endl;
}
char buf[2000];
int serverLength = sizeof(server);
int bytesIn = recvfrom(sock, buf, 2000, 0, (sockaddr*)&server, &serverLength);
if (bytesIn > 0)
{
cout << "Message Received :" << bytesIn << endl;
}
}
//***** Function to call the _sendPacket function and send commands to the Camera *****//
void _packetConfig(SOCKET sock)
{
// 59 Commands and every command call _snedPacket function to send commands to camera it will working properly
}
In the above code I have to first send this 59 commands written in _packetConfig function then only camera will send Image packets I am receiving the reply of all that commands.
When I run wireshark also with that code I can see that after these 59 commands
the camera is giving 3580*51 packets.i.e 51 frames and each frame contain 3580 packets
Thank you for posting your code. There are actually a few things wrong with it so first I will post some code that works as a reference and then mention the major issues I noticed with yours afterwards.
OK, here is some code that works for me:
#include <WinSock2.h> // ** before** windows.h
#include <WS2tcpip.h>
#include <iostream>
#include <stdio.h>
#include <Windows.h>
#include <assert.h>
#pragma comment (lib, "ws2_32.lib")
const int port = 3956;
// main
int main (char argc, char* argv[])
{
WSADATA wsadata;
WORD version = MAKEWORD(2, 2);
int err = WSAStartup (MAKEWORD (2, 2), &wsadata);
if (err)
{
std::cout << "WSAStartup failed, error: " << err << std::endl;
return 255;
}
char buf [1444];
bool send = argc > 1 && _stricmp (argv [1], "send") == 0;
if (send)
{
// Send
SOCKET skt_out = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
assert (skt_out != INVALID_SOCKET);
sockaddr_in destination_address = { };
destination_address.sin_family = AF_INET;
destination_address.sin_port = htons (port);
inet_pton (AF_INET, "192.168.1.2", &destination_address.sin_addr);
memset (buf, 'Q', sizeof (buf));
printf ("Sending: ");
for ( ; ; )
{
sendto (skt_out, buf, sizeof (buf), 0, (const sockaddr *) &destination_address, sizeof (destination_address));
printf (".");
Sleep (50);
}
closesocket (skt_out);
WSACleanup ();
return 0;
}
// Receive
SOCKET skt_in = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
assert (skt_in != INVALID_SOCKET);
int receive_buffer_size = 65536;
if ((setsockopt (skt_in, SOL_SOCKET, SO_RCVBUF, (const char *) &receive_buffer_size, sizeof (int)) ) < 0)
std::cout << "Could not set SO_RCVBUF, error: " << WSAGetLastError () << std::endl;
sockaddr_in receive_address = { };
receive_address.sin_family = AF_INET;
receive_address.sin_port = htons (port);
receive_address.sin_addr.s_addr = htonl (INADDR_ANY);
if (bind (skt_in, (const sockaddr *) &receive_address, sizeof (receive_address)) == -1)
{
std::cout << "bind failed , error: " << WSAGetLastError () << std::endl;
return 255;
}
int packetCounter = 0;
printf ("Receiving: ");
for ( ; ; )
{
int bytesIn = recvfrom (skt_in, buf, sizeof (buf), 0, NULL, 0);
if (bytesIn > 0)
std::cout << "Packet received:" << bytesIn << " bytes (" << ++packetCounter << ")" << std::endl;
else
std::cout << "Receive error: " << WSAGetLastError () << std::endl;
}
closesocket (skt_in);
WSACleanup ();
return 0;
}
To run this in 'send' mode, specify send as the first argument on the command line. Otherwise it acts as a receiver (aka server).
So what's wrong with your code? Well, in no particular order:
as we already said, you shouldn't be using SOCK_RAW
you need to call bind on the receiving socket so that it knows what port to listen on. The sockaddr *from parameter to recvfrom doesn't mean what you think it means (please check the docs). You will see I pass this as NULL.
you were misinterpreting the return value from WSAStartup. Again, please check the docs.
But having said all that, it was essentially the call to bind that you were missing. I rewrote the code because yours is rather messy.
Also, important detail, UDP doesn't guarantee delivery - there are a number of reasons why a packet that has been sent does not get received or might even get received out of sequence (does your camera sequence the packets in some way?)
You need to cater for that in the logic of your application (and it that's a problem, it's better to use TCP, which does guarantee packet delivery and sequencing).
Related
I'm currently working on an instant messaging system that require a server and a client to communicate between each other.
I tried it in C++ using the default socket API.
The problem is that even if both programs (server & client) compile fine, there isn't any socket sent from the client that reaches the server.
I don't know what did I do wrong here (I went over my code like 5 times and even did it again from scratch, no success).
I used "debugs" messages to locate the problems and they all concern the processing loops that I use.
// code from the server
#include <stdio.h>
#include <tchar.h>
#include <winsock2.h>
#include <stdlib.h>
#include <iostream>
#include <thread>
#include <vector>
#include <Ws2tcpip.h>
#include <string>
int main()
{
std::locale::global(std::locale("fr-FR"));
WSAData wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
std::cout << "Error initializing winsock";
return -1;
}
SOCKET server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server == INVALID_SOCKET)
{
std::cout << "Error initializing the socket ";
return -2;
}
const unsigned short port = 9999;
sockaddr_in addr;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(port);
addr.sin_family = AF_INET;
int res = bind(server, (sockaddr*)&addr, sizeof(addr));
if (res != 0)
{
std::cout << "Error when binding";
return -3;
}
res = listen(server, SOMAXCONN);
if (res != 0)
{
std::cout << "Error on calling listen";
return -4;
}
std::cout << "Server successfully launched" << std::endl;
char buffer[1025];
while (true)
{
sockaddr_in from = { 0 };
int addrlen = sizeof(from);
SOCKET newClient = accept(server, (SOCKADDR*)(&from), &addrlen);
if (newClient != SOCKET_ERROR)
{
std::cout << "Client connected successfully" << std::endl;
int Bytes = recv(newClient, buffer, 1024, 0);
if (Bytes <= 0)
{
break;
}
std::cout << "Message received from client : " << buffer << std::endl;
send(newClient, buffer, 1024, 0); // send it back to client
}
}
return 0;
}
// code from the client
#include <stdio.h>
#include <tchar.h>
#include <winsock2.h>
#include <stdlib.h>
#include <iostream>
#include <thread>
#include <vector>
#include <Ws2tcpip.h>
#include <string>
#define _WINSOCK_DEPRECATED_NO_WARNINGS
void sendMessage(SOCKET s);
void recvMessage(SOCKET s);
int main()
{
std::locale::global(std::locale("fr-FR"));
WSAData wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
std::cout << "Error initializing winsock";
return -1;
}
SOCKET server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server == INVALID_SOCKET)
{
std::cout << "Error initializing the socket ";
return -2;
}
sockaddr_in addr;
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_family = AF_INET;
addr.sin_port = htons(9999);
int res = bind(server, (sockaddr*)&addr, sizeof(addr));
if (res != 0)
{
std::cout << "Error when binding";
return -3;
}
if (connect(server, (const sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)
{
std::cout << "Erreur when connecting : " << WSAGetLastError() << std::endl;
return -4;
}
std::cout << "You are connected to server" << std::endl;
std::thread sending(sendMessage, server);
std::thread receiving(recvMessage, server);
sending.detach();
receiving.detach();
while (true)
{ }
return 0;
}
void sendMessage(SOCKET s)
{
while (true)
{
std::string buff;
std::cout << "Type your message :" << std::endl;
std::getline(std::cin, buff);
std::cout << std::endl;
int Bytes = send(s, buff.c_str(), 1024, 0);
if (Bytes <= 0)
{
break;
}
}
}
void recvMessage(SOCKET s)
{
while (true)
{
char buffer[1025];
int Bytes = recv(s, buffer, 1024, 0);
if (Bytes <= 0)
{
break;
}
std::cout << "The server sent : " << buffer << std::endl;
}
}
The server should display the message that a client has connected when the client is launched and displays the chat command, but the only thing displayed in the server console is the message saying that the server has launched correctly... Yet the client displays the message supposedly "received" by the server.
PS : I'm aware the code doesn't need that many "include" statements, it's just I didn't remember which ones contained which functions so I'd rather include more than not enough for anybody wanting to compile the code.
Several Things:
First, this is wrong:
send(s, buff.c_str(), 1024, 0)
You're basically telling send that the buffer it addresses is a full 1kb, and to send it all. It hasn't a clue how much memory there is actually valid, and knows nothing about terminated strings.
Second, the client setup is wrong. Don't bind to a client socket; connect is sufficient. Notice these:
int res = bind(server, (sockaddr*)&addr, sizeof(addr));
if (res != 0)
{
std::cout << "Error when binding";
return -3;
}
if (connect(server, (const sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)
{
std::cout << "Erreur when connecting : " << WSAGetLastError() << std::endl;
return -4;
}
That bind shouldn't be there. The connect will bind to the socket if the connection can be made. Removing the bind section of the client, fixing the buffer management to be correct, and putting closesocket calls where they belong, and your program will be much further down the road to functional. There are still some question logic workflows, but at least the connectivity will be setup better.
I'm currently working on a simple server/client application using C++ in Visual Studio to send a message from one computer to another via an Ethernet/LAN cable connection. I am using code for both client and server that I found online.
When I run the programs on the same computer, I can receive messages from the server. However, if I run the client program on one computer and run the server program on another computer, I do not receive any messages.
Since I am just using an Ethernet cable to communicate between two computers, I set the IP addresses (from Local Network Sharing, Adapter settings, TCP/IPv4) to be specific for both computers, such that the server computer is 10.0.1.2 and the client computer is 10.0.1.1, both with a subnet mask of 255.255.255.0. And then, in the code, I use addr.sin_addr.s_addr = inet_addr("10.0.1.2") for server and addr.sin_addr.s_addr = inet_addr("10.0.1.1") for client accordingly.
But I am still having the problem of sending messages from one computer to another.
Here is the code:
/////////////////////Client Code///////////////////////////////
#pragma comment(lib,"ws2_32.lib")
#pragma warning(disable:4996)
#include <WinSock2.h>
#include <iostream>
int main()
{
//Winsock Startup
WSAData wsaData;
WORD DllVersion = MAKEWORD(2, 1);
if (WSAStartup(DllVersion, &wsaData) != 0) //If WSAStartup returns anything other than 0, then that means an error has occured in the WinSock Startup.
{
MessageBoxA(NULL, "Winsock startup failed", "Error", MB_OK | MB_ICONERROR);
exit(1);
}
SOCKADDR_IN addr; //Address to be binded to our Connection socket
int sizeofaddr = sizeof(addr); //Need sizeofaddr for the connect function
addr.sin_addr.s_addr = inet_addr("10.0.1.1");
addr.sin_port = htons(139); //Port = 139
addr.sin_family = AF_INET; //IPv4 Socket
SOCKET Connection = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //Set Connection socket
if (connect(Connection, (SOCKADDR*)&addr, sizeofaddr) != 0) //If we are unable to connect...
{
MessageBoxA(NULL, "Failed to Connect", "Error", MB_OK | MB_ICONERROR);
return 0; //Failed to Connect
}
std::cout << "Connected!" << std::endl;
int rec = 0;
char MOTD[256];
while (1)
{
recv(Connection, MOTD, sizeof(MOTD), NULL); //Receive Message of the Day buffer into MOTD array
std::cout << "MOTD:" << MOTD << std::endl;
std::cout << "rec:" << rec << std::endl;
rec++;
Sleep(500);
}
}
/////////////////////Server Code///////////////////////////////
#pragma comment(lib,"ws2_32.lib")
#pragma warning(disable:4996)
#include <WinSock2.h>
#include <iostream>
int main()
{
//WinSock Startup
WSAData wsaData;
WORD DllVersion = MAKEWORD(2, 1);
if (WSAStartup(DllVersion, &wsaData) != 0) //If WSAStartup returns anything other than 0, then that means an error has occured in the WinSock Startup.
{
MessageBoxA(NULL, "WinSock startup failed", "Error", MB_OK | MB_ICONERROR);
return 0;
}
SOCKADDR_IN addr; //Address that we will bind our listening socket to
int addrlen = sizeof(addr); //length of the address (required for accept call)
addr.sin_addr.s_addr = inet_addr("10.0.1.2");
addr.sin_port = htons(139); //Port
addr.sin_family = AF_INET; //IPv4 Socket
SOCKET sListen = socket(AF_INET, SOCK_STREAM, NULL); //Create socket to listen for new connections
bind(sListen, (SOCKADDR*)&addr, sizeof(addr)); //Bind the address to the socket
listen(sListen, SOMAXCONN); //Places sListen socket in a state in which it is listening for an incoming connection. Note:SOMAXCONN = Socket Oustanding Max Connections
int counter = 0;
SOCKET newConnection; //Socket to hold the client's connection
newConnection = accept(sListen, (SOCKADDR*)&addr, &addrlen); //Accept a new connection
if (newConnection == 0) //If accepting the client connection failed
{
std::cout << "Failed to accept the client's connection." << std::endl;
}
else //If client connection properly accepted
{
std::cout << "Client Connected!" << std::endl;
while (counter <100)
{
char MD[256] = "Hi there."; //Create buffer with message
send(newConnection, MD, sizeof(MD), NULL); //Send MD buffer
counter++;
}
}
system("pause");
return 0;
}
I really don't know what to do now. I can ping from one computer to another, but I can not make it work to send a message from one computer to another via the Ethernet connection.
The main problem is that the client is connecting to the wrong IP. The server's IP is 10.0.1.2, but the client is trying to connect to 10.0.1.1 instead. That is why it doesn't work across multiple computers. The client needs to connect to the server's IP, not the client's IP.
Also, you are making several other mistakes in general.
On the server side, you are ignoring the return values of bind() and listen(), and accept() returns INVALID_SOCKET (-1) on error instead of 0.
On the client side, you are ignoring the return value of recv(). It returns -1 on error, 0 on graceful disconnect, and > 0 for the number of bytes actually read. You need to pay attention to that, especially when you are sending the read data to std::cout. You are passing a char[] to operator<<, so the data must be null-terminated, but recv() does not do guarantee that. So, either:
add a null terminator to the end of the char[] data after reading it:
int numRead = recv(Connection, MOTD, sizeof(MOTD)-1, NULL);
if (numRead <= 0) break;
MOTD[numRead] = 0; // <-- here
std::cout << "MOTD:" << MOTD << std::endl;
pass the char[] to std::cin.write() instead of operator<<, specifying the actual number of bytes read in the count parameter:
int numRead = recv(Connection, MOTD, sizeof(MOTD), NULL);
if (numRead <= 0) break;
std::cout << "MOTD:";
std::cout.write(MOTD, numRead); // <-- here
std::cout << std::endl;
And your MOTD protocol is not very well designed in general. The server is sending 256 bytes (if you are lucky, send() can send fewer bytes!) for every message, even though only 9 bytes are actually being used. So you are wasting bandwidth. The client is expecting to receive exactly 256 bytes every time (which is not guaranteed, as recv() may receive fewer bytes!). A better design is to have the server send strings that have a terminating delimiter at the end, such as a line break or a null terminator, and then have the client read in a loop until it receives that delimiter, THEN process the data that has been received.
Try something more like this:
/////////////////////Client Code///////////////////////////////
#pragma comment(lib,"ws2_32.lib")
#pragma warning(disable:4996)
#include <WinSock2.h>
#include <Windows.h>
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
//Winsock Startup
WSAData wsaData;
int iResult = WSAStartup(MAKEWORD(2, 1), &wsaData);
if (iResult != 0) //If WSAStartup returns anything other than 0, then that means an error has occured in the WinSock Startup.
{
std::cout << "Winsock Startup Failed, Error " << iResult << std:endl;
return 1;
}
SOCKADDR_IN addr = {};
addr.sin_family = AF_INET; //IPv4 Socket
addr.sin_addr.s_addr = inet_addr("10.0.1.2"); //Address to be connected to
addr.sin_port = htons(139); //Port = 139
SOCKET Connection = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //Create socket to establish new connection with
if (Connection == INVALID_SOCKET)
{
iResult = WSAGetLastError();
std::cout << "Failed to Create Socket, Error " << iResult << std::endl;
WSACleanup();
return 1; //Failed to Connect
}
if (connect(Connection, (SOCKADDR*)&addr, sizeof(addr)) == SOCKET_ERROR) //If we are unable to connect...
{
iResult = WSAGetLastError();
std::cout << "Failed to Connect, Error " << iResult << std::endl;
closesocket(Connection);
WSACleanup();
return 1; //Failed to Connect
}
std::cout << "Connected!" << std::endl;
int rec = 0;
char buf[256], *ptr, *start, *end;
int numRead;
std::string MOTD;
int iExitCode = 0;
while (true)
{
numRead = recv(Connection, buf, sizeof(buf), NULL); //Receive data
if (numRead == SOCKET_ERROR)
{
iResult = WSAGetLastError();
std::cout << "Failed to Read, Error " << iResult << std:endl;
iExitCode = 1;
break;
}
if (numRead == 0)
{
std::cout << "Server disconnected!" << std::endl;
break;
}
start = buf;
end = buf + numRead;
do
{
// look for MOTD terminator
ptr = std::find(start, end, '\0');
if (ptr == end)
{
// not found, need to read more...
MOTD.append(start, end-start);
break;
}
// terminator found, display current MOTD and reset for next MOTD...
MOTD.append(start, ptr-start);
std::cout << "MOTD:" << MOTD << std::endl;
std::cout << "rec:" << rec << std::endl;
rec++;
MOTD = "";
start = ptr + 1;
}
while (start < end);
}
closesocket(Connection);
WSACleanup();
return iExitCode;
}
/////////////////////Server Code///////////////////////////////
#pragma comment(lib,"ws2_32.lib")
#pragma warning(disable:4996)
#include <WinSock2.h>
#include <Windows.h>
#include <iostream>
#include <string>
bool sendAll(SOCKET s, const void *buf, int size)
{
const char *ptr = (const char*) buf;
while (size > 0)
{
int numSent = send(s, ptr, size, NULL);
if (numSent == SOCKET_ERROR) return false;
ptr += numSent;
size -= numSent;
}
return true;
}
int main()
{
//WinSock Startup
WSAData wsaData;
int iResult = WSAStartup(MAKEWORD(2, 1), &wsaData);
if (iResult != 0) //If WSAStartup returns anything other than 0, then that means an error has occured in the WinSock Startup.
{
std::cout << "WinSock Startup Failed, Error " << iResult << std::endl;
return 1;
}
SOCKADDR_IN addr = {};
addr.sin_family = AF_INET; //IPv4 Socket
addr.sin_addr.s_addr = INADDR_ANY; //Address that we will bind our listening socket to. INADDR_ANY = all local IPv4 addresses
addr.sin_port = htons(139); //Port
SOCKET sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //Create socket to listen for new connections
if (sListen == INVALID_SOCKET)
{
iResult = WSAGetLastError();
std::cout << "Failed to Create Socket, Error " << iResult << std::endl;
closesocket(sListen);
WSACleanup();
return 1;
}
if (bind(sListen, (SOCKADDR*)&addr, sizeof(addr)) == SOCKET_ERROR) //Bind the address to the socket
{
iResult = WSAGetLastError();
std::cout << "Failed to Bind Socket, Error " << iResult << std::endl;
closesocket(sListen);
WSACleanup();
return 1;
}
if (listen(sListen, SOMAXCONN) == SOCKET_ERROR) //Places sListen socket in a state in which it is listening for an incoming connection. Note:SOMAXCONN = Socket Outstanding Max Connections
{
iResult = WSAGetLastError();
std::cout << "Failed to Listen, Error " << iResult << std::endl;
closesocket(sListen);
WSACleanup();
return 1;
}
SOCKET newConnection; //Socket to hold the client's connection
int iExitCode = 0;
do
{
std::cout << "Waiting for Client to Connect..." << std::endl;
int addrlen = sizeof(addr); //length of the address (required for accept call)
newConnection = accept(sListen, (SOCKADDR*)&addr, &addrlen); //Accept a new connection
if (newConnection == INVALID_SOCKET) //If accepting the client connection failed
{
iResult = WSAGetLastError();
std::cout << "Failed to accept a client's connection, Error " << iResult << std::endl;
iExitCode = 1;
break;
}
std::cout << "Client Connected!" << std::endl;
for (int counter = 0; counter < 100; ++counter)
{
std::string MOTD = "Hi there."; //Create buffer with message
if (!sendAll(newConnection, MOTD.c_str(), MOTD.length()+1))
{
iResult = WSAGetLastError();
std::cout << "Failed to Send, Error " << iResult << std::endl;
break;
}
}
closesocket(newConnection);
std::cout << "Client Disconnected!" << std::endl;
}
while (true);
closesocket(sListen);
WSACleanup();
return iExitCode;
}
Thank you for all the answers and comments! I solved the problem via changing the port number. Apparently, some of the port numbers are reserved so I have to assign another one.
I'm using libev + non-blocking sockets to send a request to a server. I'm using Keep Alive because I need to send future requests to the destination over this same connection.
Behavior
Run the program and it fetches the URL and logs to console, as expected.
After doing this, wait and don't push ctrl+c to exit the program.
Expected
App should stay open because event loop is waiting for future responses but should not console log anything after the initial response.
Actual
Leave the app running. After 30+ seconds, it will start to console log the same response over and over and over again without end.
Question
Why is libev calling my callback (example_cb) repeatedly when no new request was sent and no new response data was received? How can I fix this?
#include <ev.h>
#include <stdio.h>
#include <iostream>
#include <ctype.h>
#include <cstring>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <unistd.h>
#include <sstream>
#include <fstream>
#include <string>
using namespace std;
void sendRequest(int sockfd)
{
puts("------");
puts("sendRequest() was called");
stringstream ss;
ss << "GET /posts/11 HTTP/1.1\r\n"
<< "Host: jsonplaceholder.typicode.com\r\n"
<< "Accept: application/json\r\n"
<< "\r\n";
string request = ss.str();
if (send(sockfd, request.c_str(), request.length(), 0) != (int)request.length()) {
cout << "Error sending request." << endl;
exit(1);
}
cout << "Request sent. No err occured." << endl;
}
static void delay_cb(EV_P_ ev_timer *w, int revents)
{
puts("------");
puts("delay_cb() was called");
sendRequest(3);
}
static void example_cb(EV_P_ ev_io *w, int revents)
{
puts("------");
puts("example_cb() was called");
int sockfd = 3;
size_t len = 80*1024, nparsed; // response must be <= 80 Kb
char buf[len];
ssize_t recved;
recved = recv(sockfd, &buf, len, 0);
if (recved < 0) {
perror("recved was <1");
}
// don't process keep alives
if (buf[0] != '\0') {
std::cout << buf << std::endl;
}
// clear buf
buf[0] = '\0';
std::cout << "buf after clear attempt: " << buf << std::endl;
}
int example_request()
{
std::string hostname = "jsonplaceholder.typicode.com";
int PORT = 80;
struct sockaddr_in client;
struct hostent * host = gethostbyname(hostname.c_str());
if (host == NULL || host->h_addr == NULL) {
cout << "Error retrieving DNS information." << endl;
exit(1);
}
bzero(&client, sizeof(client));
client.sin_family = AF_INET;
client.sin_port = htons( PORT );
memcpy(&client.sin_addr, host->h_addr, host->h_length);
// create a socket
int sockfd = socket(PF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
cout << "Error creating socket." << endl;
exit(1);
}
cout << "Socket created" << endl;
// enable keep alive
int val = 1;
setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof val);
if (connect(sockfd, (struct sockaddr *)&client, sizeof(client)) < 0) {
close(sockfd);
cout << "Could not connect" << endl;
exit(1);
}
cout << "Socket connected" << endl;
// make non-blocking
int status = fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL, 0) | O_NONBLOCK);
if (status == -1) {
perror("ERROR making socket non-blocking");
}
std::cout << "Socket set to non-blocking" << std::endl;
std::cout << "Sockfd is: " << sockfd << std::endl;
return sockfd;
}
int main(void)
{
// establish socket connection
int sockfd = example_request();
struct ev_loop *loop = EV_DEFAULT;
ev_io example_watcher;
ev_io_init(&example_watcher, example_cb, sockfd, EV_READ);
ev_io_start(loop, &example_watcher);
// used to send the request 2 sec later
ev_timer delay_watcher;
ev_timer_init(&delay_watcher, delay_cb, 2, 0.0);
ev_timer_start(loop, &delay_watcher);
ev_run(loop, 0);
return 0;
}
Edit: Code updated with suggestions from comments
The source of the problem is that you do not check recved == 0 condition which corresponds to the other side closing the connection. When that happens the OS sets the socket into "closed mode" which (at least under linux) is always ready for reading and subsequent calls to recv will always return 0.
So what you need to do is to check for that condition, call close(fd); on the file descriptor (possibly with shutdown before) and ev_io_stop on the associated watcher. If you wish to continue at that point then you have to open a new socket and eo_io_start new watcher.
My aim is to write C++ program which receives data from network using udp protocol. OS - linux. I have few questions.
I want to make sure that I can use linux C libraries to write C++ program.
Is anywhere exists full tutorial which expailns step by step how to program using sockets in linux? ( I know that in network is many tutorials, but I'm looking for something which help me receive udp data from INTERNET, not from another program on the same device.).
I see in terminal ( using tcpdump) that my computer receive udp packages addressed to specified port. What's wrong with my program which looks like this
class Connection
{
private:
char * buffer;
int bufferSize;
int sock;
struct sockaddr_in server;
struct sockaddr_in other;
socklen_t addressLength;
public:
Connection(string address, int port, int bufferSize);
~Connection();
int reciveData();
};
Connection::Connection(string address, int port, int bufferSize)
{
this->addressLength = sizeof(this->server);
this->sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(this->sock == -1)
{
cout << "Socket error!" << endl;
exit(1);
}
memset(&(this->server), 0, sizeof(this->server));
this->server.sin_family = AF_INET;
this->server.sin_port = htons(port);
this->server.sin_addr.s_addr = htonl(INADDR_ANY);
if( bind(this->sock, (sockaddr *) &(this->server), this->addressLength) == -1 )
{
cout << "Bind socket error!" << endl;
exit(1);
}
this->bufferSize = bufferSize;
this->buffer = new char[bufferSize];
cout << "Socket created!" << endl;
}
int Connection::receiveData()
{
int returned;
fflush(stdout);
if( (returned =recvfrom(this->sock, this->buffer, this->bufferSize, 0, (sockaddr *) &(this->other), &this->addressLength)) == -1)
{
cout << "Receiving error!" << endl;
exit(1);
}
return returned;
}
When i call receiveData() nothing's happening - I think program waits for some udp package ( and i don't know why he does not receive it).
Could someone explain me difference between udp server and client program ?
Thanks a lot.
When calling recvfrom(), you are passing it a pointer to this->addressLength. On input, the length needs to be the complete size of the address buffer. On output, the actual address length is returned. So recvfrom() might be altering your addressLength member, affecting subsequent code. Use a local variable instead:
int Connection::receiveData()
{
int returned;
int addrlen = sizeof(this->other);
fflush(stdout);
returned = recvfrom(this->sock, this->buffer, this->bufferSize, 0, (sockaddr *) &(this->other), &addrLen);
if( returned == -1 )
{
cout << "Receiving error!" << endl;
exit(1);
}
return returned;
}
Alternatively, use a separate member variable instead:
class Connection
{
private:
char * buffer;
int bufferSize;
int sock;
struct sockaddr_in server;
struct sockaddr_in other;
socklen_t serverAddressLength;
socklen_t otherAddressLength;
public:
Connection(string address, int port, int bufferSize);
~Connection();
int reciveData();
};
Connection::Connection(string address, int port, int bufferSize)
{
this->serverAddressLength = sizeof(this->server);
this->sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(this->sock == -1)
{
cout << "Socket error!" << endl;
exit(1);
}
if(this->sock == -1)
{
cout << "Socket error!" << endl;
exit(1);
}
memset(&(this->server), 0, sizeof(this->server));
this->server.sin_family = AF_INET;
this->server.sin_port = htons(port);
this->server.sin_addr.s_addr = htonl(INADDR_ANY);
if( bind(this->sock, (sockaddr *) &(this->server), this->serverAddressLength) == -1 )
{
cout << "Bind socket error!" << endl;
exit(1);
}
this->bufferSize = bufferSize;
this->buffer = new char[bufferSize];
cout << "Socket created!" << endl;
}
int Connection::receiveData()
{
int returned;
fflush(stdout);
this->otherAddressLength = sizeof(this->other);
if( (returned =recvfrom(this->sock, this->buffer, this->bufferSize, 0, (sockaddr *) &(this->other), &this->otherAddressLength)) == -1)
{
cout << "Receiving error!" << endl;
exit(1);
}
return returned;
}
I'm trying to write a simple program that will receive a string of max 20 characters and print that string to the screen.
The code compiles, but I get a bind() failed: 10038. After looking up the error number on msdn (socket operation on nonsocket), I changed some code from
int sock;
to
SOCKET sock
which shouldn't make a difference, but one never knows.
Here's the code:
#include <iostream>
#include <winsock2.h>
#include <cstdlib>
using namespace std;
const int MAXPENDING = 5;
const int MAX_LENGTH = 20;
void DieWithError(char *errorMessage);
int main(int argc, char **argv)
{
if(argc!=2){
cerr << "Usage: " << argv[0] << " <Port>" << endl;
exit(1);
}
// start winsock2 library
WSAData wsaData;
if(WSAStartup(MAKEWORD(2,0), &wsaData)!=0){
cerr << "WSAStartup() failed" << endl;
exit(1);
}
// create socket for incoming connections
SOCKET servSock;
if(servSock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)==INVALID_SOCKET)
DieWithError("socket() failed");
// construct local address structure
struct sockaddr_in servAddr;
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = INADDR_ANY;
servAddr.sin_port = htons(atoi(argv[1]));
// bind to the local address
int servAddrLen = sizeof(servAddr);
if(bind(servSock, (SOCKADDR*)&servAddr, servAddrLen)==SOCKET_ERROR)
DieWithError("bind() failed");
// mark the socket to listen for incoming connections
if(listen(servSock, MAXPENDING)<0)
DieWithError("listen() failed");
// accept incoming connections
int clientSock;
struct sockaddr_in clientAddr;
char buffer[MAX_LENGTH];
int recvMsgSize;
int clientAddrLen = sizeof(clientAddr);
for(;;){
// wait for a client to connect
if((clientSock=accept(servSock, (sockaddr*)&clientAddr, &clientAddrLen))<0)
DieWithError("accept() failed");
// clientSock is connected to a client
// BEGIN Handle client
cout << "Handling client " << inet_ntoa(clientAddr.sin_addr) << endl;
if((recvMsgSize = recv(clientSock, buffer, MAX_LENGTH, 0)) <0)
DieWithError("recv() failed");
cout << "Word in the tubes: " << buffer << endl;
closesocket(clientSock);
// END Handle client
}
}
void DieWithError(char *errorMessage)
{
fprintf(stderr, "%s: %d\n", errorMessage, WSAGetLastError());
exit(1);
}
The problem is with
servSock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)==INVALID_SOCKET
which does not associate as you think it does. Why would you even want to write something like that, what's wrong with
SOCKET servSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(servSock == INVALID_SOCKET)
DieWithError("socket() failed");
?