ConnectEx requires the socket to be "initially bound", but to what? - windows

The ConnectEx function requires an "unconnected, previously bound socket". Indeed, if I omit the bind step in my example (see below), ConnectEx fails with WSAEINVAL.
Here's my current understanding: before calling ConnectEx, bind the socket to INADDR_ANY and port 0 (unless it is already bound):
struct sockaddr_in addr;
ZeroMemory(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = 0;
rc = bind(sock, (SOCKADDR*) &addr, sizeof(addr));
if (rc != 0) { ... bind failed; call WSAGetLastError to see why ... }
Or for an IPv6 socket:
struct sockaddr_in6 addr;
ZeroMemory(&addr, sizeof(addr));
addr.sin6_family = AF_INET6;
addr.sin6_addr = in6addr_any;
addr.sin6_port = 0;
rc = bind(sock, (SOCKADDR*) &addr, sizeof(addr));
if (rc != 0) { ... bind failed; call WSAGetLastError to see why ... }
This lets the operating system assign a local address to our socket (as opposed to the remote address we are connecting to). connect does this step automatically, but ConnectEx does not.
My questions are:
Is my assessment correct?
Is there a way to do this automatic bind that is agnostic to the address family, or will I have to handle each of AF_INET, AF_INET6, AF_BTH (Bluetooth), etc. manually?
Working ConnectEx example (also on Gist: https://gist.github.com/4158972):
#include <stdio.h>
#include <WinSock2.h>
#include <MSWSock.h>
#include <WS2tcpip.h>
#pragma comment(lib, "Ws2_32.lib")
struct mswsock_s {
LPFN_CONNECTEX ConnectEx;
} mswsock;
static BOOL load_mswsock(void)
{
SOCKET sock;
DWORD dwBytes;
int rc;
/* Dummy socket needed for WSAIoctl */
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET)
return FALSE;
{
GUID guid = WSAID_CONNECTEX;
rc = WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER,
&guid, sizeof(guid),
&mswsock.ConnectEx, sizeof(mswsock.ConnectEx),
&dwBytes, NULL, NULL);
if (rc != 0)
return FALSE;
}
rc = closesocket(sock);
if (rc != 0)
return FALSE;
return TRUE;
}
int main(int argc, char *argv[])
{
int rc;
BOOL ok;
WSADATA wsaData;
SOCKET sock;
rc = WSAStartup(MAKEWORD(2,2), &wsaData);
if (rc != 0) {
printf("WSAStartup failed: %d\n", rc);
return 1;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
printf("Your computer is from the wrong millenium.\n");
WSACleanup();
return 1;
}
if (!load_mswsock()) {
printf("Error loading mswsock functions: %d\n", WSAGetLastError());
return 1;
}
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET) {
printf("socket: %d\n", WSAGetLastError());
return 1;
}
/* ConnectEx requires the socket to be initially bound. */
{
struct sockaddr_in addr;
ZeroMemory(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = 0;
rc = bind(sock, (SOCKADDR*) &addr, sizeof(addr));
if (rc != 0) {
printf("bind failed: %d\n", WSAGetLastError());
return 1;
}
}
/* Issue ConnectEx and wait for the operation to complete. */
{
OVERLAPPED ol;
ZeroMemory(&ol, sizeof(ol));
sockaddr_in addr;
ZeroMemory(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("173.194.37.36"); // google.com
addr.sin_port = htons(80);
ok = mswsock.ConnectEx(sock, (SOCKADDR*) &addr, sizeof(addr), NULL, 0, NULL, &ol);
if (ok) {
printf("ConnectEx succeeded immediately\n");
} else if (WSAGetLastError() == ERROR_IO_PENDING) {
printf("ConnectEx pending\n");
DWORD numBytes;
ok = GetOverlappedResult((HANDLE) sock, &ol, &numBytes, TRUE);
if (ok)
printf("ConnectEx succeeded\n");
else
printf("ConnectEx failed: %d\n", WSAGetLastError());
} else {
printf("ConnectEx failed: %d\n", WSAGetLastError());
return 1;
}
}
/* Make the socket more well-behaved. */
rc = setsockopt(sock, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0);
if (rc != 0) {
printf("SO_UPDATE_CONNECT_CONTEXT failed: %d\n", WSAGetLastError());
return 1;
}
/* This will fail if SO_UPDATE_CONNECT_CONTEXT was not performed. */
rc = shutdown(sock, SD_BOTH);
if (rc != 0) {
printf("shutdown failed: %d\n", WSAGetLastError());
return 1;
}
printf("Done\n");
return 0;
}

connect does this step automatically, but ConnectEx does not.
Correct.
Is my assessment correct?
Yes.
Is there a way to do this automatic bind that is agnostic to the address family, or will I have to handle each of AF_INET, AF_INET6, AF_BTH (Bluetooth), etc. manually?
I believe that INADDR_ANY is a bunch of zeros in all address families, so you could just try using the memset() and omitting the assignment to addr.sin_addr.s_addr completely. Whether this is kosher, portable, politically correct etc. is another question into which I will not enter.
It seems pretty curious that Microsoft didn't manage to have ConnectEx() call bind() internally, considering that saving system calls is the motivation for its existence, and also considering that most programs never bind an outbound socket at all.

It is possible to get the bind address for ConnectEx in an address family independent way.
Solution 1
Call getaddrinfo with the following options:
pServiceName = "0"
hints.ai_flags = AI_PASSIVE
hints.ai_family = address family of the socket
Then use the first result of the returned address list.
To get the address family of the socket you can use getsockopt with SO_PROTOCOL_INFOW.
Solution 2
Use SOCKADDR_STORAGE for the address structure and call INETADDR_SETANY which is defined in MSTcpIP.h. It supports AF_INET and AF_INET6.

Related

Winsock "recv" doesn't return on a non-graceful connection termination

I'm running the following code:
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
// Need to link with Ws2_32.lib
#pragma comment (lib, "Ws2_32.lib")
// #pragma comment (lib, "Mswsock.lib")
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "8081"
int __cdecl main(void)
{
WSADATA wsaData;
int iResult;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET;
struct addrinfo* result = NULL;
struct addrinfo hints;
int iSendResult;
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
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 server address and port
iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Create a SOCKET for connecting to server
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
// Setup the TCP listening socket
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);
iResult = listen(ListenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
printf("listen failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
while (true)
{
printf("Waiting for connection...\n");
// Accept a client socket
ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET) {
printf("accept failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
else
{
printf("Received connection !\n");
}
// No longer need server socket
//closesocket(ListenSocket);
// Receive until the peer shuts down the connection
do {
printf("Before recv\n");
iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
printf("After recv\n");
if (iResult > 0) {
printf("Bytes received: %d\n", iResult);
recvbuf[iResult] = 0;
// Echo the buffer back to the sender
printf("%s\n", recvbuf);
}
else if (iResult == 0)
printf("Connection closing...\n");
else {
printf("recv failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
} while (iResult > 0);
printf("After loop !!\n");
iResult = shutdown(ClientSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
// cleanup
closesocket(ClientSocket);
//
}
// shutdown the connection since we're done
WSACleanup();
return 0;
}
When a client terminates the connection ungracefully, i.e., just shuts down without calling close() or anything, the recv() function is blocking and doesn't return.
I've read in the docs of the recv function that:
If the socket is connection oriented and the remote side has shut down the connection gracefully, and all data has been received, a recv will complete immediately with zero bytes received. If the connection has been reset, a recv will fail with the error WSAECONNRESET.
But that's not the case. In my case, the recv() just blocks the execution. I guess that the docs refer to a situation in which you call recv() AFTER the connection has been closed by the peer, but in my case, the connection is being closed after recv() was called.
How can I handle this?
An abnormal connection loss (where network communication just stops, vs a reset which is explicit) takes time for the OS to detect it. TCP is designed to be resilient in case of a network outage. recv() WILL fail eventually, but it could take up to several minutes for the OS to timeout internally and invalidate the connection. Until that happens, no errors are reported.
If you don't want to wait the necessary time for the OS to invalidate the connection, you will have to enable use of your own timeout in your own code, such as by calling select() before recv(), or by using setsockopt(SO_RCVTIMEO), WSAIoctl(SIO_KEEPALIVE_VALS), etc to make recv() exit on a timeout. Then you can close the socket if the timeout elapses.

RIOSendEx get error 10022 but connect + RIOSend works well

I'm learning Windows Registered I/O, I found a sample project from the website "https://github.com/zeliard/RIOEchoServer", It does well on my computer.
However, if I change this code from the listening server side to the actively sending client side, I find that connect + RIOSend works fine, but RIOSendEx will definitely give an error code of 10022!
#include <WinSock2.h>
#include <MSWsock.h>
#include <WS2tcpip.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
int main(int argc, char * argv[])
{
static const wchar_t SERVER[] = L"127.0.0.1";
static const unsigned short PORTNUM = 54321;
static const DWORD RIO_PENDING_RECVS = 1;
static const DWORD RIO_PENDING_SENDS = 1;
static const DWORD RECV_BUFFER_SIZE = 1024;
static const DWORD SEND_BUFFER_SIZE = 1024;
static const DWORD ADDR_BUFFER_SIZE = 64;
static const DWORD RIO_MAX_RESULTS = 1;
WSADATA wsadata;
if (0 != ::WSAStartup(0x202, &wsadata))
{
printf_s("WSAStartup Error: %d\n", GetLastError());
exit(0);
}
/// RIO socket
SOCKET socket = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, WSA_FLAG_REGISTERED_IO);
if (socket == INVALID_SOCKET)
{
printf_s("WSASocket Error: %d\n", GetLastError());
exit(0);
}
/// RIO function table
GUID functionTableId = WSAID_MULTIPLE_RIO;
DWORD dwBytes = 0;
RIO_EXTENSION_FUNCTION_TABLE rio;
if (NULL != WSAIoctl(socket, SIO_GET_MULTIPLE_EXTENSION_FUNCTION_POINTER, &functionTableId, sizeof(GUID), (void**)&rio, sizeof(rio), &dwBytes, NULL, NULL))
{
printf_s("WSAIoctl Error: %d\n", GetLastError());
exit(0);
}
/// rio's completion manner: iocp
HANDLE hIOCP = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);
if (NULL == hIOCP)
{
printf_s("CreateIoCompletionPort Error: %d\n", GetLastError());
exit(0);
}
OVERLAPPED overlapped;
RIO_NOTIFICATION_COMPLETION completionType;
completionType.Type = RIO_IOCP_COMPLETION;
completionType.Iocp.IocpHandle = hIOCP;
completionType.Iocp.CompletionKey = NULL;
completionType.Iocp.Overlapped = &overlapped;
/// creating RIO CQ, which is bigger than (or equal to) RQ size
RIO_CQ completionQueue = rio.RIOCreateCompletionQueue(RIO_PENDING_RECVS + RIO_PENDING_SENDS, &completionType);
if (completionQueue == RIO_INVALID_CQ)
{
printf_s("RIOCreateCompletionQueue Error: %d\n", GetLastError());
exit(0);
}
/// creating RIO RQ
/// SEND and RECV within one CQ (you can do with two CQs, seperately)
RIO_RQ requestQueue = rio.RIOCreateRequestQueue(socket, RIO_PENDING_RECVS, 1, RIO_PENDING_SENDS, 1, completionQueue, completionQueue, NULL);
if (requestQueue == RIO_INVALID_RQ)
{
printf_s("RIOCreateRequestQueue Error: %d\n", GetLastError());
exit(0);
}
/// registering RIO buffers for SEND
char sendBuffer[SEND_BUFFER_SIZE];
RIO_BUFFERID sendRioBufferId = rio.RIORegisterBuffer(sendBuffer, static_cast<DWORD>(sizeof(sendBuffer)));
if (sendRioBufferId == RIO_INVALID_BUFFERID)
{
printf_s("RIORegisterBuffer Error: %d\n", GetLastError());
exit(0);
}
RIO_BUF sendRioBuffer;
sendRioBuffer.BufferId = sendRioBufferId;
sendRioBuffer.Offset = 0;
sendRioBuffer.Length = SEND_BUFFER_SIZE;
/// registering RIO buffers for ADDR
char addrBuffer[ADDR_BUFFER_SIZE];
RIO_BUFFERID addrRioBufferId = rio.RIORegisterBuffer(addrBuffer, static_cast<DWORD>(sizeof(addrBuffer)));
if (addrRioBufferId == RIO_INVALID_BUFFERID)
{
printf_s("RIORegisterBuffer Error: %d\n", GetLastError());
exit(0);
}
RIO_BUF addrRioBuffer;
addrRioBuffer.BufferId = addrRioBufferId;
addrRioBuffer.Offset = 0;
addrRioBuffer.Length = ADDR_BUFFER_SIZE;
/// registering RIO buffers for RECV and then, post pre-RECV
char recvBuffer[RECV_BUFFER_SIZE];
RIO_BUFFERID recvRioBufferId = rio.RIORegisterBuffer(recvBuffer, static_cast<DWORD>(sizeof(recvBuffer)));
if (recvRioBufferId == RIO_INVALID_BUFFERID)
{
printf_s("RIORegisterBuffer Error: %d\n", GetLastError());
exit(0);
}
RIO_BUF recvRioBuffer;
recvRioBuffer.BufferId = recvRioBufferId;
recvRioBuffer.Offset = 0;
recvRioBuffer.Length = RECV_BUFFER_SIZE;
/// posting pre RECVs
if (!rio.RIOReceiveEx(requestQueue, &recvRioBuffer, 1, NULL, &addrRioBuffer, NULL, 0, 0, &recvRioBuffer))
{
printf_s("RIOReceive Error: %d\n", GetLastError());
exit(0);
}
//////////////////////////////////////////////////////////////////////////
// active send code begin ...
//////////////////////////////////////////////////////////////////////////
sendRioBuffer.Length = 5;
memcpy_s(sendBuffer, RECV_BUFFER_SIZE, "hello", sendRioBuffer.Length);
sockaddr_in * address = reinterpret_cast<sockaddr_in *>(addrBuffer);
memset(address, 0x0, ADDR_BUFFER_SIZE);
address->sin_family = AF_INET;
address->sin_port = htons(PORTNUM);
if (::InetPton(AF_INET, SERVER, &address->sin_addr) <= 0)
{
printf_s("inet_pton Error: %d\n", GetLastError());
exit(0);
}
#if 0 // connect + RIOSend is OK
if (SOCKET_ERROR == ::connect(socket, reinterpret_cast<struct sockaddr *>(address), sizeof(*address)))
{
printf_s("Connect Error: %d\n", GetLastError());
exit(0);
}
if (!rio.RIOSend(requestQueue, &sendRioBuffer, 1, 0, &sendRioBuffer))
{
printf_s("RIOSend Error: %d\n", GetLastError());
exit(0);
}
#else // RIOSendEx not work
if (!rio.RIOSendEx(requestQueue, &sendRioBuffer, 1, NULL, &addrRioBuffer, NULL, NULL, 0, &sendRioBuffer))
{
printf_s("RIOSendEx Error: %d\n", GetLastError());
exit(0);
}
#endif // 0
INT notifyResult = rio.RIONotify(completionQueue);
if (notifyResult != ERROR_SUCCESS)
{
printf_s("RIONotify Error: %d\n", GetLastError());
exit(0);
}
DWORD numberOfBytes = 0;
ULONG_PTR completionKey = 0;
OVERLAPPED* pOverlapped = 0;
RIORESULT results[RIO_MAX_RESULTS];
if (!::GetQueuedCompletionStatus(hIOCP, &numberOfBytes, &completionKey, &pOverlapped, INFINITE))
{
printf_s("GetQueuedCompletionStatus Error: %d\n", GetLastError());
exit(0);
}
memset(results, 0, sizeof(results));
ULONG numResults = rio.RIODequeueCompletion(completionQueue, results, RIO_MAX_RESULTS);
if (0 == numResults || RIO_CORRUPT_CQ == numResults)
{
printf_s("RIODequeueCompletion Error: %d\n", GetLastError());
exit(0);
}
const RIORESULT & res = results[0];
if (0 != res.Status)
{
printf_s("RIOSend(Ex) Error: %d\n", res.Status);
exit(0);
}
printf_s("RIOSend(Ex) OK\n");
//////////////////////////////////////////////////////////////////////////
// active send code end ...
//////////////////////////////////////////////////////////////////////////
if (SOCKET_ERROR == ::closesocket(socket))
{
printf_s("closesocket Error: %d\n", GetLastError());
}
rio.RIOCloseCompletionQueue(completionQueue);
rio.RIODeregisterBuffer(sendRioBufferId);
rio.RIODeregisterBuffer(recvRioBufferId);
rio.RIODeregisterBuffer(addrRioBufferId);
return 0;
}
wish your help, Thanks!
yanrk
From RIOSendEx documentation:
sends network data on ... a bound ... UDP socket
Your example will work if you add those lines before calling RIOSendEx:
sockaddr_in addr{}; // zero-initialized
addr.sin_family = AF_INET;
if (SOCKET_ERROR == ::bind(socket, (struct sockaddr *)&addr, sizeof(addr)))
{
printf("bind failed\n");
exit(0);
}
if (!rio.RIOSendEx(requestQueue ...
You can bind to some particular port (not recommended):
addr.sin_port = htons(5001);
Or leave it zero for OS to choose.
Aparently, RIOSendEx do not perform an implicit bind (unlike WSASendTo).
The reason for this might be that bind is a complicated process that might involve waiting and APC and all kinds of stuff, while whole idea of RIO is to pay upfront.
connect + RIOSendEx doesn't make sense. Since you specified remote address with connect function you can't send data through that socket anywhere else. RIOSendEx is supposed to be used with datagrams.
You have not set the Destination IP-Address in the RioSendEx-Function:
Copy the content of your address-Buffer into the associated Buffer of addrRioBuffer.
e.g.:
memcpy_s(addrBuffer, ADDR_BUFFER_SIZE, address, sizeof(sockaddr_in));
if (!rio.RIOSendEx(requestQueue, &sendRioBuffer, 1, NULL, &addrRioBuffer, NULL, NULL, 0, &sendRioBuffer))
{
printf_s("RIOSendEx Error: %d\n", GetLastError());
exit(0);
}
// […]
I will post a working exampel in the next day´s.
http://www.thbweb.eu

Why my threaded winsock server won't crash?

I have implemented a c++ winsock (win 32) with intention of crashing using an strcpy command. The socket itself is instantiated inside a thread. However, when I put the strcpy inside the recv loop, it does not seem to crash.
I know there is nothing wrong with the compiler since writing one with just strcpy crashes, I am thinking it is related to recv since it initiates a block on the process.
Here is the full code below for the sever, the crash I am trying to implement is in the form of strcpy(a, "AAAA..."); in regular circumstances it should crash, but here it does not. I would like to know why.
#define WIN32_LEAN_AND_MEAN
#include<windows.h>
#include<winsock2.h>
#include<stdlib.h>
#include<stdio.h>
#include<ws2tcpip.h>
#include <iostream.h>
#include <conio.h>
#define DEFAULT_PORT "1133"
#define DEFAULT_BUFLEN 512
struct thread_data
{
int m_id;
thread_data(int id) : m_id(id){}
};
char a[10];
DWORD WINAPI ServerThread (LPVOID pParam){
WSADATA wsaData;
struct addrinfo *result =NULL;
struct addrinfo hints;
SOCKET ListenSocket = INVALID_SOCKET;
do{
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
int iResult;
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
iResult = getaddrinfo(NULL,DEFAULT_PORT,&hints, &result);
if (iResult != 0 ){
printf("get addrinfo failed with error %d\n", iResult);
WSACleanup();
return 1;
} //end if
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket ==0){
printf("socket creation failed with error %d\n", WSAGetLastError());
}
//bind socket
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;
}
printf ("initializing socket\n ");
iResult= listen(ListenSocket,SOMAXCONN);
if (iResult== SOCKET_ERROR){
printf("listen failed with %d\n",WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
SOCKET client ;
sockaddr_in from;
int fromlen=sizeof(from);
char temp[1024];
char temp_to_send[1024];
char temp_to_send_vuln[512];
printf("accepting client request\n");
client=accept(ListenSocket, (struct sockaddr*) &from, &fromlen);
printf("accepted socket\n");
iResult =1;
int iSendResult =1;
char c;
//start receiving from client
while( (iResult = recv(client,temp,1024,0 )) > 0 ){
c = temp[0];
temp[iResult] = '\0';
if(c!=13)
strcat(temp_to_send,temp);
//if enter is hit echo sent data to client
if(c ==13 ){
printf("sending %s \n",temp_to_send);
//I WANT TO CRASH THE PGORAM HERE!!
strcpy(a,"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
strcat(temp_to_send_vuln,temp_to_send);
strcat(temp_to_send_vuln,"\r\n");
iSendResult = send(client,temp_to_send,strlen(temp_to_send),0);
//if user types "exit" the client socket would terminate
if (strcmp(temp_to_send,"exit") ==0){
printf("exit entered\n");
closesocket(client);
WSACleanup();
break;
}
re-initialize variables for next input
temp[0] = '\0';
temp_to_send[0] = '\0';
}//end if(ch ==13)
}//end recv
printf("termination of socket with error %d and buffer length is ", WSAGetLastError());
printf("client said %s\n", temp) ;
if (iResult == SOCKET_ERROR){
printf("receiving failed with error %d",WSAGetLastError());
}
if (iSendResult == SOCKET_ERROR){
printf("seding failed with error %d", WSAGetLastError());
closesocket(client);
WSACleanup();
exit(1);
}
} while(1);
closesocket(ListenSocket);
WSACleanup();
printf("program ended\n");
return 0;
}
//the main function that calls the thread
int main(void)
{
//create thread here
CreateThread(NULL, 0 ,ServerThread, new thread_data(0), 0,0);
//terminate program when escape character is hit
while(_getch()!=27);
return 0;
}
Your strcpy() call is just trashing a and then whatever else happens to be after it in global memory; it's undefined whether it'll crash or not. If you really want to crash out, just call strcpy( NULL, "whatever" ).

UDP socket programming in windows

I developed code to receive udp packets from the port. But after calling recvfrom() nothing is happening. Following is my code and output.
#include "udpSocket.h"
int main(void)
{
SOCKET sockID;
WSADATA wsaData = {0};
FILE *udp;
char buf[512];
static int recvData;
int iResult = 0;
int sock_len = sizeof(fepAddr);
int recvResult;
int seqNo = 0;
static int outOfSeqCnt = 0;
FILE *fp = fopen("outOfSeq.txt","a");
if((udp = fopen("udpData.txt","w")) == 0)
printf("udpData.txt not opened\n");
printf("\n-------------------------------------\n");
printf("\tUDP Packet Receiver\n");
printf("-------------------------------------\n");
printf("\n Enter Destination FEP IP Address : ");
scanf_s("%s",inputData.destIPAddr,16);
printf("\n Enter Destination port from which to receive data : ");
scanf_s("%d",&inputData.portNo,5);
printf("\n Enter No.of iterations : ");
scanf_s("%d",&inputData.noIteration,2);
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if(iResult < 0)
{
printf("windows socket startup error\n");
}
sockID = socket(PF_INET, SOCK_DGRAM, 0);
if(sockID < 0)
{
printf("Socket creation error\n");
WSACleanup();
}
else
{
printf("Socket Created\n");
}
fepAddr.sin_family = AF_INET;
fepAddr.sin_port = htons(inputData.portNo);
//fepAddr.sin_addr.s_addr = inet_addr(inputData.destIPAddr);
fepAddr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(sockID, (struct sockaddr *)&fepAddr, sizeof(struct sockaddr)) < 0)
{
printf("bind() failed: %ld.\n", WSAGetLastError());
closesocket(sockID);
return 0;
}
else
{
printf("bind() is OK!\n");
}
memset(udpBuf, 0, sizeof(udpBuf));
recvData = 1;
while (recvData)
{
printf("receiving data\n");
recvResult = recvfrom(sockID, udpBuf, sizeof(udpBuf), 0,(struct sockaddr *)&fepAddr, &sock_len);
if (recvResult <= 0) {
printf("Socket receive()-error\n");
goto exit;
}
else
printf("Sock success\n");
printf("completed rx data\n");
//puts(udpBuf);
fprintf(udp, "%s", udpBuf);
//fwrite(udpBuf, sizeof(udpBuf), 1, udp);
}
inputData.noIteration--;
if (inputData.noIteration <= 0)*/
recvData-- ;
}
exit:
if(udp)
{
fclose(udp);
udp = 0;
}
//shutdown socket
closesocket(sockID);
fclose(udp);
return 0;
}
- output::::
UDP Packet Receiver
Enter Destination FEP IP Address : 192.168.13.25
Enter Destination port from which to receive data : 2013
Enter No.of iterations :
0
Socket Created
bind() is OK!
receiving data
Well, first off your bind call should use sizeof(fepAddr) (which I assume is struct sockaddr_in) instead of sizeof(struct sockaddr) to give it a chance of actually binding to the correct address.
Second, are you sure that someone is actually sending you data? otherwise recvfrom will block by default.

Linux to WinXP over UDP lag

I'm having a problem with a UDPSocket wrapper I've written. I have a high bandwidth low latency local network over which I'm sending UDP packets back and forth. I don't have a concern too much for reliability of packet arrival, but it is incredibly important that the packets that do arrive do so quickly. Here's the relevant code for setting up a socket:
bool UDPSocket::create() {
int on = 1;
#ifdef WIN32
if(WSAStartup(MAKEWORD(1,1), &SocketInfo) != 0) {
MessageBox(NULL, "Cannot initialize WinSock", "WSAStartup", MB_OK);
}
#endif
m_sock = socket(PF_INET, SOCK_DGRAM, 0);
#ifdef WIN32
if(setsockopt(m_sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) == SOCKET_ERROR)
return false;
#else
if(setsockopt(m_sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) == -1)
return false;
#endif
addrLen = sizeof(struct sockaddr);
return true;
}
bool UDPSocket::bind(const int port) {
if(!is_valid())
return false;
m_addr.sin_family = AF_INET;
m_addr.sin_addr.s_addr = htonl(INADDR_ANY);
m_addr.sin_port = htons(port);
if(::bind(m_sock, (struct sockaddr*)&m_addr, sizeof(m_addr))<0) {
std::cout << "UDPSocket: error on bind" << std::endl;
return false;
}
return true;
}
bool UDPSocket::send(const std::string s) const {
const char* buf = s.c_str();
::sendto(m_sock, buf, strlen(buf), 0, (const sockaddr*)&clientAddr, addrLen);
return true;
}
bool UDPSocket::setDestination(const std::string ip, const int port) {
memset(&clientAddr, 0, sizeof(clientAddr));
clientAddr.sin_family = AF_INET;
clientAddr.sin_addr.s_addr = inet_addr(ip.c_str());
clientAddr.sin_port = htons(port);
return true;
}
int UDPSocket::recv(std::string& s) const {
char buffer[MAXRECV + 1];
struct timeval tv;
fd_set fdset;
int rc, nread;
memset(&buffer, 0, sizeof(buffer));
FD_ZERO(&fdset);
FD_SET(m_sock, &fdset);
tv.tv_sec = 0;
tv.tv_usec = m_timeout;
rc = select(m_sock + 1, &fdset, (fd_set *) 0, (fd_set *) 0, &tv);
if(FD_ISSET(m_sock, &fdset)) {
#ifdef WIN32
nread = ::recvfrom(m_sock, buffer, MAXRECV, 0, (sockaddr*)&clientAddr, const_cast< int * __w64 >(&addrLen));
#else
nread = ::recvfrom(m_sock, buffer, MAXRECV, 0, (sockaddr*)&clientAddr, (socklen_t*)&addrLen);
#endif
if(nread < 0) {
return -1;
} else if(nread == 0) {
return 0;
}
s = std::string(buffer);
return nread;
} else {
return 0;
}
}
void UDPSocket::set_non_blocking(const bool b) {
mNonBlocking = b;
#ifdef WIN32
u_long argp = b ? 1 : 0;
ioctlsocket(m_sock, FIONBIO, &argp);
#else
int opts = fcntl(m_sock, F_GETFL);
if(opts < 0) return;
if(b)
opts |= O_NONBLOCK;
else
opts &= ~O_NONBLOCK;
fcntl(m_sock, F_SETFL, opts);
#endif
}
My user code, on both ends, create a "sending" and "receiving" UDPSocket and bind them to their respective ports, then use send() to send data and recv() to receive. On one hand, the linux side seems to receive practically immediately, but the Windows side has a delay up to 1 second before receiving data. However, ::recv() never returns 0 in this time. Am I missing something obvious?
have you tried all four combinations (linux->linux, win->linux, linux->win, win->win)? which have delays and which not?
also, use a packet sniffer (like tcpdump or wireshark) to see if the delay is before or after hitting the wire.
It's not a direct answer. May be you can try tools like ttcp (http://www.pcausa.com/Utilities/pcattcp.htm), which can both test tcp and udp performance. And, you may also check their source code, which is in public domain.
If you've got the time to experiment, try an IOCP version of the code.
I never trusted the win select implementation, with its 64 socket limit.

Resources