c++ winsock server-client remote connection - c++

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);
}

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
}

Trying to create UDP Server

I'm trying to create a UDP Server ,though without even client connecting to it, it recieves a connection...
(It writes in the console - New Connection a lot, so I guess it gets a new connection suddenly...)
#include <iostream>
#include <string>
#include <WinSock2.h>
#include <ws2tcpip.h>
#include <Windows.h>
#pragma comment(lib, "ws2_32.lib")
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;
}
int main()
{
SOCKET ListenSocket = ServerOn();
SOCKET ClientSocket;
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr("10.0.0.2");
service.sin_port = htons(2583);
while(true)
{
if (ClientSocket = accept(ListenSocket, (SOCKADDR*)&service, NULL))
{
std::cout << "New Connection!" << std::endl;
}
}
}
Why is it getting connected without I ran anything? Maybe something else tries to connect to my server?
Thanks!
Two things: I don't think the IP address of your server can be 0.0.0.0, but instead 10.0.0.2; and also, UDP doesn't support the concept of 'accept'. There are just packets, and you can either bind a socket to a port, then receive packets from a specific IP (with recvfrom), or you can receive packets from anyone, with recv. The latter will be useful in case of a server. Note that you manually have to keep track of each connected client with a sockaddr_in structure.

WSAGetLastError returns WSAENOTSOCK - Cause?

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.

Unable to get local host IP address from getsockname?

I am able to get the port returned, but the IP is not. Should I be using something else other than getsockname? thx
if ((sock = ::socket(AF_INET, SOCK_STREAM, 0)) == -1) {
c.Format("Socket Error: %d", GetLastError());
tcpMESSAGE = 1;
break;
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(4000); //port setting
server_addr.sin_addr.s_addr = INADDR_ANY;
if (::bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) {
c.Format("Bind Error: %d", GetLastError());
tcpMESSAGE = 1;
break;
}
if(1==1){
int len = sizeof server_addr;
if(::getsockname(sock,(struct sockaddr*)&server_addr,&len) == -1)
MessageBox("Error local host ip");
c.Format("local addr %s:%u\n errno: %d",inet_ntoa(server_addr.sin_addr),ntohs(server_addr.sin_port), errno);
MessageBox(c);
}
You are binding to INADDR_ANY, but you have not connected the socket to a peer yet, so there is no IP for getsockname() to return. After a connection has been established via connect() or accept(), then getsockname() can return the specific IP that is being used for that connection. Binding alone is not enough, unless you bind to a specific IP, which you are not doing.