WSAGetLastError returns WSAENOTSOCK - Cause? - c++

I have something like this in my code
WSADATA wsadata;
int error = WSAStartup(0x0202, &wsadata);
SOCKADDR_IN target; //Socket address information
target.sin_family = AF_INET; // address family Internet
target.sin_port = htons (5005);
target.sin_addr.s_addr = inet_addr ("127.0.0.1");
clntSocket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); //Create socket
if (::connect(clntSocket, (SOCKADDR *)&target, sizeof(target)) == SOCKET_ERROR)
{
//Could not connect
__debugbreak();
}
else
{
//Connected - Now receive data
do
{
char my_stream[800];
iResult = recv(clntSocket,my_stream,sizeof(my_stream),0);
if(iResult<0)
{
int a = WSAGetLastError();
//Receives 10038 - WSAENOTSOCK
}
} while( iResult > 0 );
}
And I would sometimes (occasionally) get 10038. Which states that
Socket operation on nonsocket.
An operation was attempted on something that is not a socket. Either the socket handle parameter did not reference a valid socket,or for select, a member of an fd_set was not valid.
Am I doing something wrong while setting up the socket ? Any suggestions on how to fix the problem ?

Either:
You never opened the socket.
You have corrupted the handle value.
You have closed the socket and then continued to use it.

Related

winsock always returning -1 on socket

I'm trying to connect to my server on port 69 using winsock2.h. Everything appears to be compiling correctly but in a debugger maincommsock is always equal to -1. I can't seem to figure out why it isn't working, and need help. Not very experienced with socket programming, and not sure what to do now!. Any help will be greatly appreciated.
I'm not 100% sure what else to try. This is basically a function that establishes a connection on a socket, and sets connection to true, so that it can loop until it connects.
int maincommsock;
bool connection = false;
static void establishconn() {
maincommsock = socket(AF_INET, SOCK_STREAM, 0);
if (maincommsock == -1) {
connection = false;
}
//OutputDebugString((LPCSTR)commservers[1]);
/*
struct hostent *host;
if ((host = gethostbyname(SERV_ADDR)) == NULL) {
connection = FALSE;
}
*/
SOCKADDR_IN sockaddr;
sockaddr.sin_port = 69;
sockaddr.sin_family = AF_INET;
sockaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
//sockaddr.sin_addr.s_addr = *((unsigned long*)host->h_addr);
if (connect(maincommsock, (SOCKADDR *)(&sockaddr), sizeof(sockaddr)) != 1) {
connection = true;
}
}
EDIT
I used WSAStartup, and the error I'm currently getting is No connection could be made because the target machine actively refused it."
EDIT 2
used htons on the port. It says the operation completed successfully but no connections show up on the server
EDIT 3
I'm going to test it on linux, to make sure that it is actually a server side error and not a problem with my code. I'll keep you guys updated.
Your error handling is a bit lacking.
First off, when an error does occur, STOP what you are doing. Right now, you are not stopping, you just move on to the next API call as if no error occured.
Second, your error handling on connect() is wrong. connect() returns 0 on success and -1 on failure, but you are checking its return value for != 1 so you are going to treat successes and failures the same way.
Try this instead:
static SOCKET establishconn(const char *addr, u_short port)
{
SOCKET commsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (commsock == INVALID_SOCKET)
return INVALID_SOCKET;
//OutputDebugStringA(addr);
SOCKADDR_IN sockaddr = {};
sockaddr.sin_family = AF_INET;
sockaddr.sin_port = htons(port);
sockaddr.sin_addr.s_addr = inet_addr(addr);
if (sockaddr.sin_addr.s_addr == INADDR_NONE)
{
struct hostent *host = gethostbyname(addr);
if (!host)
{
closesocket(commsock);
return INVALID_SOCKET;
}
sockaddr.sin_addr.s_addr = *((u_long*) host->h_addr);
}
if (connect(commsock, (SOCKADDR &sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
{
closesocket(commsock);
return INVALID_SOCKET;
}
return commsock;
}
Then you can do this:
WSAStartup(...);
...
SOCKET maincommsock = establishconn("127.0.0.1", 69);
if (maincommsock != INVALID_SOCKET)
{
...
closesocket(maincommsock);
}
...
WSACleanup();
Berkeley sockets require the address and port information to be presented in network byte order. Winsock follows this API:
All of the data in the SOCKADDR_IN structure, except for the address family, must be specified in network-byte-order (big-endian).
Windows Dev Center
Use htons() to convert the port value from host to network byte order.
sockaddr.sin_port = htons(69);
inet_addr() already returns a value in network byte order.

Writing Client and Server, UDP

I'm trying to write a simple client and server using UDP.
I can send data from the client to the server, and the server recieves it well, but when I send the data from the server to the client, it doesnt work at all...
(It doesnt detect anything, and is stuck on recvfrom function..
Here is my Server code :
SOCKET ServerOn()
{
SOCKET ListenSocket;
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR)
{
exit(0);
}
// Create a SOCKET for listening for
// incoming connection requests.
ListenSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (ListenSocket == INVALID_SOCKET)
{
WSACleanup();
exit(1);
}
// The sockaddr_in structure specifies the address family,
// IP address, and port for the socket that is being bound.
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr("0.0.0.0");
service.sin_port = htons(2583);
if (bind(ListenSocket,(SOCKADDR *) & service, sizeof (service)) == SOCKET_ERROR)
{
closesocket(ListenSocket);
WSACleanup();
exit(2);
}
return ListenSocket;
}
In this function, I'm initializing the server on port 2583.
Here is my other code in the server :
int size = sizeof(service);
char *data = new char[500];
recvfrom(s,data, 500, NULL, (SOCKADDR*)&service, &size); // Getting a new connection
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr("10.0.0.1");
service.sin_port = htons(2583);
int addrSize = sizeof(service);
if (sendto(s, "123", 3, NULL, (struct sockaddr*)&service, addrSize) != 3)
printf("%d", WSAGetLastError()); // Print error if did not send successfully
"10.0.0.1" is the IP of the Client (I made sure it is)...
I didnt found a way to get the IP automaticly from the socket, so I'm just putting it right away for now...
Here is my client code :
SOCKET ConnectToServer()
{
//----------------------
// Initialize Winsock
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR)
{
return NULL;
}
//----------------------
// Create a SOCKET for connecting to server
SOCKET ConnectSocket;
ConnectSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (ConnectSocket == INVALID_SOCKET)
{
WSACleanup();
return NULL;
}
//----------------------
// The sockaddr_in structure specifies the address family,
// IP address, and port of the server to be connected to.
sockaddr_in clientService;
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr(Default_IP.c_str()); // IP
clientService.sin_port = htons(Default_Port); // Port
//----------------------
// Connect to server.
iResult = connect(ConnectSocket, (SOCKADDR *) & clientService, sizeof (clientService)); // Connecting
while (iResult == SOCKET_ERROR) // ERROR, could not connect. keep trying
{
iResult = connect(ConnectSocket, (SOCKADDR *) & clientService, sizeof (clientService)); // Connecting
}
return ConnectSocket;
}
In this code, I'm connecting to the client.
and here is the rest of the client code :
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr("10.0.0.1");
service.sin_port = htons(2583);
s = ConnectToServer();
sendto(s, "123", 3, NULL, (struct sockaddr*)&service, addrSize);
while(true)
{
result = recvfrom(s, (char*)waveIn, NUMPTS * sizeof(short int), NULL, (struct sockaddr *)&service, &addrSize);
if (result > 0)
{
std::cout << "New Data!" << std::endl;
}
else
printf("%d\n", WSAGetLastError());
}
the sendto function in the client does work, and the server recieves it, though when the server tries to send data back to the client, it recieves nothing, and it is stuck on the recvfrom function.
What am I doing wrong?
P.S - I'm running both client and server from the same computer, which means both has the same IP adress ("10.0.0.1"), but it allways worked for me when using sockets with TCP, so I've did it here too.
though, I did try use this code with 2 different computers, and I still had the same error...
Thanks!
When the server calls recvfrom(), it reports the IP:Port that the data came from. You need to send your reply back to that same IP:Port, eg:
sockaddr_in service;
int size = sizeof(service);
char data[500];
int len = recvfrom(s, data, 500, NULL, (SOCKADDR*)&service, &size);
if (len == -1)
printf("recv failed: %d", WSAGetLastError()); // Print error if did not recv successfully
else
{
if (sendto(s, "123", 3, NULL, (struct sockaddr*)&service, size) == -1)
printf("send failed: %d", WSAGetLastError()); // Print error if did not send successfully
}

c++ winsock server-client remote connection

I am trying to create a simple app that exchanges messages between two remote computers.
With the "127.0.0.1" ip it works properly, waits for the client's confirm and connects to the client, but if I try a local "192.168.0.15" or my global ip with the same port, the server connects immediately to sth without waiting for the client.
Here's part of my server code:
char ip[20] = "127.0.0.1"; int port = 19385;
SOCKET sockListen, sockConnect;
SOCKADDR_IN address;
sockConnect = socket (AF_INET, SOCK_STREAM, NULL);
address.sin_addr.s_addr = inet_addr (ip);
address.sin_family = AF_INET;
address.sin_port = htons (port);
sockListen = socket (AF_INET, SOCK_STREAM, NULL);
bind (sockListen, (SOCKADDR*)&address, AddressSize);
listen (sockListen, SOMAXCONN);
sockConnect = accept (sockListen, (SOCKADDR*)&address, &AddressSize);
...
Please suggest how to fix the problem. thx
You are not supposed to initialize your sockConnect variable with socket() before calling accept(). accept() returns a new allocated socket handle that is already connected to a client. You are leaking the socket handle that socket() allocated.
You can only bind() to an IP that belongs to a NIC of the local machine that the app is running on. You cannot bind() to an external IP.
The code you have shown is not doing any error handling at all. You need to add that, eg:
int errCode;
SOCKET sockListen = socket (AF_INET, SOCK_STREAM, NULL);
if (sockListen == INVALID_SOCKET)
{
errCode = WSAGetLastError();
// ...
}
else
{
SOCKADDR_IN address = {0};
address.sin_addr.s_addr = inet_addr (ip);
address.sin_family = AF_INET;
address.sin_port = htons (port);
if (bind (sockListen, (SOCKADDR*)&address, sizeof(address)) == SOCKET_ERROR)
{
errCode = WSAGetLastError();
// ...
}
else
{
if (listen (sockListen, SOMAXCONN) == SOCKET_ERROR)
{
errCode = WSAGetLastError();
// ...
}
else
{
int addressSize;
SOCKET sockClient = accept (sockListen, (SOCKADDR*)&address, &addressSize);
if (sockClient == INVALID_SOCKET)
{
errCode = WSAGetLastError();
// ...
}
else
{
// ...
closesocket(sockClient);
}
}
}
closesocket(sockListen);
}

recvcfrom() and sendto() ip address to be used

Actually, I want to create an application in C such that 2 people can chat with each other. Let us assume they know their IP (Actually, I think I am making the mistake here. I get my IPs from www.whatismyip.com).
void recv_data(char *from, unsigned short int Port, char *data, int data_length)
{
WSADATA wsaData;
SOCKET RecvSocket;
sockaddr_in RecvAddr;
char RecvBuf[data_length];
sockaddr_in SenderAddr;
int SenderAddrSize = sizeof (SenderAddr);
WSAStartup(MAKEWORD(2, 2), &wsaData);
RecvSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = inet_addr(from);
bind(RecvSocket, (SOCKADDR *) & RecvAddr, sizeof (RecvAddr));
recvfrom(RecvSocket, RecvBuf, data_length, 0, (SOCKADDR *) & SenderAddr, &SenderAddrSize);
int i;
for(i=0;i<=data_length-1;i++)
*(data+i)=RecvBuf[i];
WSACleanup();
}
The above is a function to receive what the other person is sending. It works great when "127.0.0.1" is the value of from but when my ip (117.193.52.176) is used, something else appears. Could anyone tell me where I am wrong ?
The address you passing to "bind" is likely wrong. Just use the IP of INADDR_ANY (0) for the call to bind. I suspect 117.193.52.176 is likely your external IP address outside of your home NAT. Your PC's real IP address is 192.168.1.2 or something like that. Type "ipconfig /all" from the command line. In any case, just bind to INADDR_ANY so you don't have to know your real IP address.
Other issues with this code:
Not checking return values from socket APIs
Don't call WSAStartup and WSACleanup for every recvfrom call. Just call WSAStartup once in your app, and don't worry about calling WSACleanup.
I'm not entirely sure if the line "char RecvBuf[data_length];" will compile. (Dynamically length static buffer on the stack? Maybe it's a new compiler feature).
Don't create a new socket for every recvfrom call. Create it once and bind to it, then use it for all subsequent send/recv calls.
5.. A more fundamnetal design problem. Unless both you and person you are communicating with are directly connected to the Internet (not NAT and no firewall), sending and receiving UDP packets will be difficult. Read the article on hole-punching here.
In any case, here's a cleaner version of your code:
int g_fWinsockInit = 0;
void initWinsock()
{
WSADATA wsaData = {};
if(!g_fWinsockInit)
{
WSAStartup(MAKEWORD(2,2), &wsaData);
g_fWinsockInit = 1;
}
}
void recv_data(char *from, unsigned short int Port, char *data, int data_length)
{
SOCKET RecvSocket;
sockaddr_in RecvAddr = {}; // zero-init, this will implicitly set s_addr to INADDR_ANY (0)
sockaddr_in SenderAddr = {}; // zero-init
int SenderAddrSize = sizeof(SendAddr);
int ret;
initWinsock();
RecvSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (RecvSocket == INVALID_SOCK)
{
printf("Error - socket failed (err = %x)\n", WSAGetLastError());
return;
}
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
ret = bind(RecvSocket, (SOCKADDR *) & RecvAddr, sizeof (RecvAddr));
if (ret < 0)
{
printf("bind failed (error = %x)\n", WSAGetLastError());
return;
}
ret = recvfrom(RecvSocket, data, data_length, 0, (SOCKADDR *) &SenderAddr, &SenderAddrSize);
if (ret < 0)
{
printf("recvfrom failed (error = %x)\n", WSAGetLastError());
}
else
{
printf("received %d bytes\n");
}
}

Receiving multiple messages Winsock2 C++

I am trying to make a program using Winsock2 where I can send a message from client to server. I can do this, but the problem is I can only send one message and then I have to restart the server to receive the next message. Here is the code for the server. The part I am really confused about is I have the recv() function in a while loop so why isn't it continuing to "receive" data?
WSADATA wsaData;
int bytes_recieved;
char data_recieve[2048];
string output;
WSAStartup(MAKEWORD(2, 2), &wsaData);
SOCKET ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
SOCKADDR_IN ServerInfo;
ServerInfo.sin_family = AF_INET;
ServerInfo.sin_addr.s_addr = INADDR_ANY;
ServerInfo.sin_port = htons(8888);
bind(ListenSocket, (LPSOCKADDR)&ServerInfo, sizeof(struct sockaddr));
listen(ListenSocket, 1);
SOCKET ClientSocket = accept (ListenSocket, NULL, NULL);
while(true)
{
bytes_recieved = recv(ClientSocket, data_recieve, 2048, 0);
if (bytes_recieved > 1)
{
cout << data_recieve;
}
}
closesocket(ClientSocket);
closesocket(ListenSocket);
WSACleanup();
The client (sender) is listed below.
WSADATA wsaData;
int bytes_sent;
char send_msg[] = "super cool message!";
WSAStartup(MAKEWORD(2, 2), &wsaData);
SOCKET ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
sockaddr_in ConnectInfo;
ConnectInfo.sin_family = AF_INET;
ConnectInfo.sin_addr.s_addr = inet_addr("127.0.0.1");
ConnectInfo.sin_port = htons(8888);
connect(ConnectSocket, (SOCKADDR*)&ConnectInfo, sizeof(ConnectInfo));
bytes_sent = send(ConnectSocket, send_msg, sizeof(send_msg), 0);
closesocket(ConnectSocket);
WSACleanup();
I am doing this in Windows 7 with a MinGW compiler. Thank you in advance.
You did not show your client sending code, but offhand, your server reading code is not taking into account that sends and receives are NOT 1-to-1 in TCP/IP programming. If a client sends 2 messages, the server may receive both messages, or even portions of them, in the same read operation! You ae telling your server socket to read 2048 bytes at a time. It will return whatever is currently available on the socket at that moment. TCP/IP is a byte stream, you need to treat it as much. That means you need to either put a delimiter in between your messages, or put a frame around them, in order to know where one message ends and the next message begins.