Getting random 10060 (conn. timeout) errors on a server socket - c++

A few users of my software have come to me recently, telling me that it doesn't work on Windows 8. After investigation it turns out that for some strange reason, my server socket doesn't always accept connections, but lets them time out.
Even stranger: it also happens when connecting to localhost, not just when accessing it remotely.
"What have you tried?"
Obvious stuff: turn off firewalls (no effect), see if other software does work (it does), try modifying random lines of code (no effect).
Less obvious stuff: use a global WSAStartup instead of one per client or server instance (no effect).
Reminder: the exact same code works fine on Windows XP and Windows 7 and it affects localhost connections as well (not a hardware issue). Also, only a third of the connections fail, the rest works fine.
Okay, now some real code, since that's a lot more useful than all these words.
Socket setup:
int iResult;
struct addrinfo *result = NULL;
struct addrinfo hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// "Resolve" our localhost
iResult = getaddrinfo(NULL, port, &hints, &result);
if (iResult != 0) {
printf("error (2) : %d\n", iResult);
return false;
}
// Create the socket
listenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (listenSocket == INVALID_SOCKET) {
freeaddrinfo(result);
printf("error (3) : %d\n", WSAGetLastError());
return false;
}
// Bind it
iResult = bind(listenSocket, result->ai_addr, result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
freeaddrinfo(result);
closesocket(listenSocket);
printf("error (4) : %d\n", WSAGetLastError());
return false;
}
freeaddrinfo(result);
// Listen
iResult = listen(listenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
closesocket(listenSocket);
printf("%d\n", WSAGetLastError());
return false;
}
As you can probably see, it's almost directly taken from MSDN and should be fine. Besides, it works for 2/3 of the connections so I really doubt it's the setup code at fault.
The receiver code:
if (listenSocket == INVALID_SOCKET) return false;
#pragma warning(disable:4127)
fd_set fds;
SOCKET client;
do {
FD_ZERO(&fds);
FD_SET(listenSocket, &fds);
struct timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
if (!select(1, &fds, NULL, NULL, &timeout)) continue; // See you next loop!
struct sockaddr_in addr;
socklen_t addrlen = sizeof(addr);
// Accept the socket
client = accept(listenSocket, (struct sockaddr *)&addr, &addrlen);
if (client == INVALID_SOCKET) {
printf("[HTTP] Invalid socket\n");
closesocket(listenSocket);
return false;
}
// Set a 1s timeout on recv()
struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
setsockopt(client, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(tv));
// Receive the request
char recvbuf[513];
int iResult;
std::stringbuf buf;
clock_t end = clock() + CLOCKS_PER_SEC; // 1s from now
do {
iResult = recv(client, recvbuf, 512, 0);
if (iResult > 0) {
buf.sputn(recvbuf, iResult);
} else if (iResult == 0) {
// Hmm...
} else {
printf("[HTTP] Socket error: %d\n", WSAGetLastError());
break;
}
} while (!requestComplete(&buf) && clock() < end);
This code spits out a "[HTTP] Socket error: 10060" error, so any code that comes after it is fairly irrelevant.
The select call is there because the actual loop does some other things as well, but I left it out because it's not socket-related.
Even stranger: Windows seems to be making actual network errors, according to Wireshark: http://i.imgur.com/BIrbD.png
I've been trying to figure this out for a while now, and I'm probably just doing something stupid, so I really appreciate all your answers.

I've been working on this annoying issue for an entire day now, and managed to eventually resolve it by rewriting the entire server from scratch and implementing it differently. I did trace the issue back to setsockopt which doesn't seem to take SO_RCVTIMEO very well anymore, causing the timeout to go to zero seconds which makes random connections time out.
My new implementation no longer uses a timeout, and is now simply non-blocking and asynchronous. Works very well but it takes a lot more code.
I'll assume that it's simply a bug in Windows 8 that will be fixed with an update before it's released. I doubt that Microsoft wanted to change the Berkeley Sockets API like this.

In Windows, SO_RCVTIMEO option requieres DWORD argument in MILLISECONDS, but not a timeval structure.
See http://msdn.microsoft.com/en-us/library/windows/desktop/ms740476(v=vs.85).aspx.
Passing timeval causes windows to interpret it as DWORD, and seconds member is read as it is milliseconds.
I don't know why timeval argument worked in Win prior 8, probably it was undocumented feature, which was removed in win 8.

Related

C++ TCP Server (Winsock) Connecting (invalid client) Instantly Then Closes

Edit: Working on a solution - turns out googling 204.204.204.204 gets me further than more descriptive requests.
Honestly. Wits end. I have no idea how I can spend an entire day doing something that took 10 minutes in Flask (Server) and Javascript (client). I need this to run in C++ and allow a client to connect via BlueStacks' port on the same machine. The client is unimportant because I can't even get that far.
I've tried WinSocks, I've tried WxWidget's networking implementation, I've even tried some random C++ wrapper thing. All of them failed (typically within the EXAMPLE! As in, copy paste and errors everywhere). So I ultimately went back to WinSockets and followed a tutorial on YouTube.
int ServerStuff() {
WSADATA WsData;
WORD ver = MAKEWORD(2, 2);
int wsOK = WSAStartup(ver, &WsData);
if (wsOK != 0) {
wxLogMessage("Can't initialize Winsock! Quitting");
return false;
}
//Create a socket
SOCKET listening = socket(AF_INET, SOCK_STREAM, 0);
if (listening == INVALID_SOCKET) {
wxLogMessage("Can't create a socket! Quitting");
return false;
}
//Bind the ip and port to a socket
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(54000);
hint.sin_addr.S_un.S_addr = INADDR_ANY; //Could also use inet_pton
bind(listening, (sockaddr*)&hint, sizeof(hint));
//Tell winsock the socket is for listening
listen(listening, SOMAXCONN);
//Wait for a connection
sockaddr_in client;
int clientSize = sizeof(client);
SOCKET clientSocket = accept(listening, (sockaddr*)&client, &clientSize);
//if (clientSocket == INVALID_SOCKET) {
// wxLogMessage("Client Invalid Socket");
// return false;
//}
char host[NI_MAXHOST]; //Client's remote name
char service[NI_MAXHOST]; //Service (port) the client is connected on
ZeroMemory(host, NI_MAXHOST);
ZeroMemory(service, NI_MAXHOST);
if (getnameinfo((sockaddr*)&client, sizeof(client), host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0) {
wxLogMessage("Can't initialize Winsock! Quitting");
}
else {
inet_ntop(AF_INET, &client.sin_addr, host, NI_MAXHOST);
wxLogMessage(host);
int wut = client.sin_port;
wxString mystring = wxString::Format(wxT("%i"), wut);
wxLogMessage("Connected on port");
wxLogMessage(mystring);
//wxLogMessage(to_string(ntohs(client.sin_port)));
}
wxLogMessage("Got this far somehow");
//Close listening socket - we don't need it anymore - later on we'll learn how to accept multiple client
closesocket(listening);
//while loop: accept and echo message back to client
char buf[4096];
while (true)
{
ZeroMemory(buf, 4096);
//Wait for client to send data
int bytesReceived = recv(clientSocket, buf, 4096, 0);
if (bytesReceived == SOCKET_ERROR) {
//wxLogMessage("ERROR in recv");
break;
}
if (bytesReceived == 0) {
wxLogMessage("Client Disconnected");
break;
}
//Echo back to client
send(clientSocket, buf, bytesReceived + 1, 0);
//Close the socket
closesocket(clientSocket);
//Cleanup winsock
WSACleanup();
wxLogMessage("Welp");
}
}
// event handlers
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
// true is to force the frame to close
ServerStuff();
//Close(true);
}
On the YouTube video ("Creating a TCP Server in C++" - not allowed to post links) this works! The command window opens, is blank infinitely until he connects a client and then the client sends a message and the server replies with the same exact message in return.
Not mine. Mine just rushes through everything and then closes. My log used to immediately quit on the commented code where it states the client socket is invalid so I commented it out. Now my output is:
204.204.204.204
Connected on port
52428
Got this far somehow
I don't know what to do. I'm just trying to send data over a same-machine TCP connection. I'm baffled as to how this is so difficult. It seems like some random process is immediately trying to connect as a client to my server ? But why is it allowed to connect on port 52428 when I'm explicitly hosting on 54000?
My goal:
Start Server
Connect to Server using a Java App within BlueStacks
Send data from Server to Client
It makes more sense for the computer to be the server because there will be multiple BlueStacks instances and I'd prefer to not have to "spawn" multiple programs / servers for what I'm doing.
I see a few mistakes in your socket code.
not calling WSACleanup() if WSAStartup() is successful and then something goes wrong afterwards.
not calling closesocket() if socket() is successful and then something goes wrong afterwards.
not zeroing out the sockaddr_in that you pass to bind(). Random bytes in the struct can cause bind() to fail.
ignoring the return values of bind(), listen(), accept(), and send().
not treating the return value of getnameinfo() correctly. It returns 0 on success, not failure.
sending +1 extra byte back to the client than you received from the client. If the client sends fewer bytes than your buffer can hold, that extra byte would be 0x00 due to your ZeroMemory() call. But if the client actually sends enough bytes to completely fill your buffer, then you would send an extra byte from memory that you do not own. If you really want to send a null terminator after everything you echo, do so explicitly. Otherwise, a true echo server should only send back exactly what it receives, no more, no less.
Try something more like this:
void ServerStuff() {
WSADATA WsData;
int ret = WSAStartup(MAKEWORD(2, 2), &WsData);
if (ret != 0) {
wxLogMessage("Can't initialize Winsock! Error: %d", ret);
return;
}
//Create a socket
SOCKET listening = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listening == INVALID_SOCKET) {
wxLogMessage("Can't create a socket! Error: %d", WSAGetLastError());
WSACleanup();
return;
}
//Bind the ip and port to a socket
sockaddr_in hint = {};
hint.sin_family = AF_INET;
hint.sin_port = htons(54000);
hint.sin_addr.s_addr = INADDR_ANY; //Could also use inet_pton
ret = bind(listening, (sockaddr*)&hint, sizeof(hint));
if (ret == SOCKET_ERROR) {
wxLogMessage("Can't bind socket! Error: %d", WSAGetLastError());
closesocket(listening);
WSACleanup();
return;
}
//Tell winsock the socket is for listening
ret = listen(listening, SOMAXCONN);
if (ret == SOCKET_ERROR) {
wxLogMessage("Can't listen on socket! Error: %d", WSAGetLastError());
closesocket(listening);
WSACleanup();
return;
}
//Wait for a connection
sockaddr_in client = {};
int clientSize = sizeof(client);
SOCKET clientSocket = accept(listening, (sockaddr*)&client, &clientSize);
if (clientSocket == INVALID_SOCKET) {
wxLogMessage("Can't accept a client! Error: %d", WSAGetLastError());
closesocket(listening);
WSACleanup();
return;
}
char host[NI_MAXHOST] = {}; //Client's remote name
ret = getnameinfo((sockaddr*)&client, sizeof(client), host, NI_MAXHOST, NULL, 0, 0);
if (ret != 0) {
wxLogMessage("Can't get client name info! Error: %d", ret);
inet_ntop(AF_INET, &(client.sin_addr), host, NI_MAXHOST);
}
wxLogMessage("Client: %s, Connected on port: %hu", host, ntohs(client.sin_port));
//Close listening socket - we don't need it anymore - later on we'll learn how to accept multiple client
closesocket(listening);
//while loop: accept and echo message back to client
char buf[4096];
int bytesReceived;
while (true)
{
//Wait for client to send data
bytesReceived = recv(clientSocket, buf, sizeof(buf), 0);
if (bytesReceived == SOCKET_ERROR) {
wxLogMessage("Can't read from client! Error: ", WSAGetLastError());
break;
}
if (bytesReceived == 0) {
wxLogMessage("Client Disconnected");
break;
}
//Echo back to client
ret = send(clientSocket, buf, bytesReceived, 0);
if (ret == SOCKET_ERROR) {
wxLogMessage("Can't send to client! Error: ", WSAGetLastError());
break;
}
}
//Close the socket
closesocket(clientSocket);
//Cleanup winsock
WSACleanup();
wxLogMessage("Welp");
}

IPC First send() and recv() calls in C++ TCP takes longer

I am using IPC (Inter-process communication) to send data between two C++ programs. For the IPC I use the basic TCP/IP Winsock2 code.
Basically the idea is that I send 3D data frames between the two applications, one processes the data using GPU/CUDA and the other displays it using a 3de party library (PCL). My applications are very rich in data (ie 30fps, 4Mb per frame), but that should not be a problem for IPC as far as I know.
So as each frame is finished processing on the GPU, I convert the frames data (X,Y,Z coords of type float; R,G,B of type uint8_t each) to bytes and send them one after the other.
Doing this I have noticed something odd. In my code I have 9 send() commands one after the other.
1ste : Sending a single char that acts as the name of the frame.
2de : A single int with the amount of 3D points incoming.
3-5th : RGB values
6-8th : XYZ values
9th : End of comms check to close the viewer application.
This whole process takes ~30ms to complete. What I found odd was where most of the time went. After timing each event I got the following:
1ste : 20ms (1 byte data)
2de : <1ms (4 bytes data)
3-5 : 2ms (921600 bytes of data)
6-8 : 3ms (3686400 bytes of data)
9th : 1ms (1 byte data)
Why is it that for the first send command it takes such a long time to complete, even when its only 1 byte of data, and then the rest of the data completes in record time. In between each time this loop runs, there is about a 20ms time delay waiting for the GPU code to finish. Does the TCP connection go into a sleep state, and if so can I disable it somehow.
TCP Socket code:
SOCKET Create_Server_Socket(PCSTR IP, PCSTR port)
{
struct addrinfo *result = NULL, *ptr = NULL, hints;
int iResult;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the local address and port to be used by the server
iResult = getaddrinfo(NULL, port, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed: %d\n", iResult);
WSACleanup();
return 1;
}
SOCKET ListenSocket = INVALID_SOCKET;
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
printf("Error at socket(): %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return 1;
}
freeaddrinfo(result);
if (listen(ListenSocket, SOMAXCONN) == SOCKET_ERROR) {
printf("Listen failed with error: %ld\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
SOCKET ClientSocket;
ClientSocket = INVALID_SOCKET;
// Accept a client socket
ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
return (ClientSocket);
}
Code in question:
iResult = send(ConnectSocket, (char*)&name, sizeof(char), 0); //Takes >20ms to complete
iResult = send(ConnectSocket, (char*)&points, 4, 0);
iResult = send(ConnectSocket, (char*)Red_t, sizeof(uint8_t) * depth_width *depth_height, 0);
iResult = send(ConnectSocket, (char*)Green_t, sizeof(uint8_t) * depth_width *depth_height, 0);
iResult = send(ConnectSocket, (char*)Blue_t, sizeof(uint8_t) * depth_width *depth_height, 0);
iResult = send(ConnectSocket, (char*)z_t, sizeof(uint16_t) * depth_width *depth_height, 0);
iResult = send(ConnectSocket, (char*)x_t, sizeof(float) * depth_width *depth_height, 0)
iResult = send(ConnectSocket, (char*)y_t, sizeof(float) * depth_width *depth_height, 0);
iResult = send(ConnectSocket, "a", sizeof(char), 0);
I am working on Windows 10 (ie the Winsock2 lib).
Thank you in advance!
You are probably suffering the penalty of "Nagle's Algorithm"
See https://en.wikipedia.org/wiki/Nagle%27s_algorithm
Long story short, there is a delay built-in to TCP/IP with the purpose of collecting enough data to be worth sending a packet before the first packet is sent. There is a TCP_NODELAY option that you can use when opening the socket to disable this, if it is a problem for you.
That having been said, if performance is of crucial importance, you might be better off using shared memory for inter-process communication rather than sockets.

Performance Windows Socket in C++ with Matlab

I am trying to create an application that sends data from a program in C++ to another in Matlab.
The size of the data is ~100 double # 1000Hz and I am having problems with reaching that frequency (even in localhost).
Using the default parameters of the socket I get ~100Hz. Also I tried using the value TCP_NODELAY to false, but that make it worse. The processor is a i7-2600 # 3.4 Hz so for sure that is not the problem. Also for the moment the only processing that I am doing with the data is save it, so also there is time consuming process.
Also I am sure that I can reach 1000 Hz because if I delete the send command, the output file has >1000 Hz.
The initialization code:
ConnectSocket = INVALID_SOCKET;
// Initialize Winsock
WSADATA wsaData;
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
int iResult;
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
}
ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the server address and port
iResult = getaddrinfo("localhost", DEFAULT_PORT, &hints, &result);
if ( iResult != 0 ) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
}
// Attempt to connect to an address until one succeeds
for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {
// Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
}
// Connect to server.
iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
continue;
}
break;
}
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET) {
printf("Unable to connect to server!\n");
WSACleanup();
}
Which is mainly (or completly) copy from the Microsoft web page.
For the sending function we have:
if (RecordingFlag){
packet[51]=values[35];
packet[52]=numchDAQ;
for (i=0;i<values[35];i++){
fprintf(file,"%.3lf,",values[i]);
packet[i] =(double)values[i];
}
//DAQ
if (numchDAQ >0){
DAQmxReadAnalogF64(taskHandle,1,10.0,DAQmx_Val_GroupByChannel,data,16,&read,NULL);
for(i=0;i<numchDAQ;i++){
fprintf(file,"%.3lf,",data[i]);
packet[(int)packet[51]+i]=(double)data[i];
}
}
//Timestamp
GetSystemTime(&st);
SystemTimeToFileTime(&st,&ft);
diftime= ((((ULONGLONG) ft.dwHighDateTime) << 32) + ft.dwLowDateTime)/10000 - MSEC_TO_UNIX_EPOCH;
fprintf(file,"%llu",diftime);
packet[0]=prueba;
prueba++;
send( ConnectSocket, (const char*)packet, sizeof(double)*53, 0 );
fprintf(file,"\n");
}
That function is called 1000 times per second.
I guess that the problem is that Windows doesn't create sockets that fast, because is waiting for the ACK from the server. But again, the server in Matlab is also very simple:
import java.net.ServerSocket
import java.io.*
j=1;
i=0;
server_socket = [];
input_socket = [];
dataByte = int8(zeros (1,424));
dataDouble = zeros(10000,53);
while (1)
try
i= i+1;
fprintf(1, 'Trying to connect %d\n',i);
server_socket = ServerSocket(31415);
server_socket.setSoTimeout(5000);
input_socket = server_socket.accept;
fprintf(1, 'Client connected\n');
while (1)
input_stream = input_socket.getInputStream;
d_input_stream = DataInputStream(input_stream);
bytes_available = input_stream.available;
while(bytes_available>0 && j<10000)
%fprintf(1, 'Reading %d bytes\n', bytes_available);
for i =1:424
dataByte(i)= d_input_stream.readByte;
bytes_available = bytes_available-1;
end
dataDouble(j,:) = typecast(dataByte,'double');
j=j+1;
end
end
% cleanup
input_socket.close;
catch
if ~isempty(server_socket)
server_socket.close;
end
if ~isempty(input_socket)
input_socket.close
end
% pause before retrying
%pause(1);
end
end
Even without make the typecast I get the same results.
Any ideas about how to solve this?
EDIT: The problem was in Matlab, it read the information too slowly. I changed the code and now works perfectly
while(bytes_available>0 && j<1000)
d_input_stream.read(dataByte,0,424);
bytes_available = bytes_available-424;
dataDouble(j,:) = typecast(dataByte,'double');
j=j+1;
end
The problem was in Matlab, it read the information too slowly. I changed the code and now works perfectly
while(bytes_available>0 && j<1000)
d_input_stream.read(dataByte,0,424);
bytes_available = bytes_available-424;
dataDouble(j,:) = typecast(dataByte,'double');
j=j+1;
end
– Priack

SNMP Extension Agent on Windows Server 2012 unable to connect to a port from which it needs data

New Update:
So on the Windows Server 2012, if I manually invoke snmp.exe from Windows\System32 to "Run as Administrator", the problem goes away. I am not able to force the SNMP Service to start as Administrator on Windows Server 2012.
Here is my scenario:
Our SNMP Extension Agent creates a windows socket to connect with one of our
Agents on a specific port number to get some configuration
information which we propagate to the MIB Browser.
When we do a fresh install of our Application and then install
SNMP on Windows Server 2012, everything works very well.
After a reboot any SNMP request to our Extension Agent is timed out
by the MIB Broswer. I debugged from the Extension Agent and found
that some how on the connect() call we are getting a "WSAEACCES
(10013) Permission denied error". Look at the comment below in the code.
The same thing works well on a Windows Server 2008.
Below is the code snippet:
struct sockaddr_in dest;
int sockfd;
char buffer;
int bytes_read;
char portNumberStr[10];
int iResult;
struct addrinfo *result = NULL, *ptr = NULL, hints;
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(2, 2);
iResult = WSAStartup(wVersionRequested, &wsaData);
if (iResult != 0)
{
int WSAError = WSAGetLastError();
return SOAP_NO_SOCKET_ERROR;
}
ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
sprintf(portNumberStr, "%d", port_number);
iResult = getaddrinfo("127.0.0.1", portNumberStr, &hints, &result);
if (iResult != 0)
{
int WSAError = WSAGetLastError();
WSACleanup();
return SOAP_NO_SOCKET_ERROR;
}
// Loop through the results addrinfo structure
bool connectionSuccess = false;
for(ptr = result; ptr != NULL; ptr = result->ai_next)
{
// Create a socket
sockfd = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
if (INVALID_SOCKET == sockfd)
{
int WSAError = WSAGetLastError();
continue;
}
iResult = connect(sockfd, ptr->ai_addr, (int)ptr->ai_addrlen); // This is the call where I get a WSAEACCES (10013) error.
if (iResult == SOCKET_ERROR)
{
int WSAError = WSAGetLastError();
closesocket(sockfd);
continue;
}
connectionSuccess = true;
break;
}
// Clean up
freeaddrinfo(result);
if(false == connectionSuccess)
{
return SOAP_ERROR;
}
// Form the Request
*localRequest = "Request goes in here"
// Send the message to the agent through a TCP socket.
send(sockfd,localRequest->c_str(),(int)localRequest->length(), 0);
// Clear out the request string so we can use it to hold a response.
*localRequest = "";
// Keep getting bytes from server until finished.
do
{
bytes_read = recv(sockfd, &buffer, sizeof(buffer), 0);
if ( bytes_read > 0 )
{
localRequest->append(1,buffer);
}
}
while ( bytes_read > 0 );
closesocket(sockfd);
WSACleanup();
The same code as a standalone application is able to communicate with our agent and get the desired data.
Kindly let me know what else I can try or if you need some more information.
Thanks and Regards
Aditya
The KB article here describes the issue our SNMP extension agent was facing on Windows 8/2012. The root cause of this as described in the article is as follows:
Any SNMP Extension agent that attempts to perform any UDP or TCP network communication on Windows Server 2012 or Windows 8 will fail. The socket connect() request will fail with the following NT status code: 0xC0000022 = STATUS_ACCESS_DENIED {Access Denied}. A process has requested access to an object, but has not been granted those access rights.
So in order to resolve the issue we need to run power shell scripts which I found here to add inbound and outbound rules for SNMP Service to talk to our agent port number.
The connect() documentation states:
WSAEACCES
An attempt to connect a datagram socket to broadcast address failed because setsockopt option SO_BROADCAST is not enabled.
...
For connectionless sockets, name can indicate any valid address, including a broadcast address. However, to connect to a broadcast address, a socket must use setsockopt to enable the SO_BROADCAST option. Otherwise, connect will fail with the error code WSAEACCES.

C++ Builder XE2, receiving tcp requests

I want to write a tcp-listener within my application, so it can be controlled by others applications.
For that I use the following snippet I found (as an example for the use of listener).
I worked with p2p-connections and Sockets once already in C#.NET, but it's either too long ago or too differently. I expect the code to stop at the listen() command and wait until there is a connection request at that port. However, instead it just continues with the next lines. Usually my Firewall should also tell me, if there is some internet-activity-attempt, but it stays silent.
What would be the next step to actually know whether there is a connection request?
Can I trigger that with a HTTP-request for 127.0.0.1:27015 using a browser?
Or could this be archived easier?
#include <winsock.h>
#pragma comment(lib, "Ws2_32.lib")
int portlisten(){
WSADATA wsaData;
int iResult = 0;
SOCKET ListenSocket = INVALID_SOCKET;
sockaddr_in service;
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR) {
wprintf(L"WSAStartup() failed with error: %d\n", iResult);
return 1;
}
//----------------------
// Create a SOCKET for listening for incoming connection requests.
ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ListenSocket == INVALID_SOCKET) {
wprintf(L"socket function failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
//----------------------
// The sockaddr_in structure specifies the address family,
// IP address, and port for the socket that is being bound.
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr("127.0.0.1");
service.sin_port = htons(27015);
iResult = bind(ListenSocket, (SOCKADDR *) & service, sizeof (service));
if (iResult == SOCKET_ERROR) {
wprintf(L"bind function failed with error %d\n", WSAGetLastError());
iResult = closesocket(ListenSocket);
if (iResult == SOCKET_ERROR)
wprintf(L"closesocket function failed with error %d\n", WSAGetLastError());
WSACleanup();
return 1;
}
//----------------------
// Listen for incoming connection requests
// on the created socket
if (listen(ListenSocket, 5) == SOCKET_ERROR)
wprintf(L"listen function failed with error: %d\n", WSAGetLastError());
wprintf(L"Listening on socket...\n");
iResult = closesocket(ListenSocket);
if (iResult == SOCKET_ERROR) {
wprintf(L"closesocket function failed with error %d\n", WSAGetLastError());
WSACleanup();
return 1;
}
WSACleanup();
return 0;
}
I expect the code to stop at the listen() command and wait until there is a connection request at that port.
No. You are thinking of accept() instead. listen() merely opens the port and then exits immediately. You have to then use accept() in a loop to accept individual client connections. It returns a new SOCKET that you use to exchange data with that specific client. You can use select() to know when a new client is trying to connect before then calling accept(), or you can let accept() block the calling thread until a client connects.
Instead of writing your own socket API code, you should use a pre-existing TCP server component, like the VCL's native TServerSocket component, or Indy's TIdTCPServer component.