c++ TCP client and server not able to communicate on local machine - c++

I have built a simple c++ TCP server and client using winsock. The code all compiles without error however either the server is refusing connections or my client is failing to connect properly.
The code is alot to put onto stackoverflow so here is a pastebin for the server and Client.
https://pastebin.com/ZQavPxsR - Server Code
https://pastebin.com/cLFVp2B1 - Client Code
sockaddr_in clientService;
clientService.sin_family = AF_INET;
InetPton(AF_INET, _T("127.0.0.1"), &clientService.sin_addr.s_addr);
clientService.sin_port = htons(port);
if (connect(clientSocket, (SOCKADDR*)&clientService, sizeof(clientService)) == SOCKET_ERROR)
{
std::cout << "Client: connect() = Failed to connect." << std::endl;
WSACleanup();
system("pause");
return 0;
}
else
{
std::cout << "Client: connect() is OK." << std::endl;
std::cout << "Client: Can start sending and reciving data... " << std::endl;
}
Above is a snippet of the code that is from the client and is responsible for making the connection with the server.
acceptSocket = accept(serverSocket, NULL, NULL);
if (acceptSocket == INVALID_SOCKET)
{
std::cout << "Accept Failed: " << WSAGetLastError() << std::endl;
WSACleanup();
return -1;
}
else
{
std::cout << "Accepted connection " << std::endl;
system("pause");
WSACleanup();
}
Above is a snippet of the code that is from the server and is responsible for accepting the connection with the client.

Your server is not initializing the service.sin_port field before calling bind(), so the code exhibits undefined behavior. Your listening socket will end up trying to bind to whatever random port value was already present in the memory that the sin_port field occupies. And if that value happens to be 0, then bind() will choose a random port from Windows' available ephemeral ports. In any case, it is very unlikely that your server is ever going to be listening on port 4679, which is the port the client is trying to connect to.
On a side note, there are some other problems with your code:
In both client and server, your calls to InetPton() should be passing in a pointer to the sockaddr_in::sin_addr field, not the sockaddr_in::sin_addr.s_addr field. It "works" only because s_addr is the sole data member of sin_addr and thus they have the same memory address. But technically, this is undefined behavior since InetPton() wants an IN_ADDR* not a ULONG*.
Your server is not exiting if listen() fails, is leaking serverSocket whether accept() succeeds or fails, and is leaking acceptSocket if accept() succeeds.
Your client is leaking clientSocket whether connect() succeeds or fails.

Related

Winsock binding on the same port

So I recently decided to dabble into winsock and network programming a bit by using a guide I found and searching the net, but I have run into a problem which I am not really sure how i should solve.
I'm trying to make a very simple chat system, I've got a working server program and client program, and if I only use on client (sending the message back to the same client) It seems to work perfectly fine. The problem appears when I try to have multiple clients connect. I get error 10048 from WSAgetlasterror and it seems to be the bind function that is the source, more specificly the fact that I am trying to bind on the same port twice, (once for each client). From looking around on msdn and forums it seems to be possible to get around this problem by using setsockopt, but I'm not really sure what changes I should make, and also if this is the smartest solution.
I mean I want the clients to connect to the same port don't I? How else will the client program know what to connect to? Or am I just missing something? As I said I have no prior experience with winsock or any other network programming so I might be doing things in a stupid way.
int listenOnPort(int portno, SOCKET& reciever, SOCKET s){
int error = WSAStartup(0x0202, &w);
if (error)
{
cout << "Error starting WSA";
return false; //for some reason we couldn't start Winsock
}
if (w.wVersion != 0x0202) //Wrong Winsock version?
{
cout << "Wrong Winsock version";
WSACleanup();
return false;
}
SOCKADDR_IN addr; // The address structure for a TCP socket
addr.sin_family = AF_INET; // Address family
addr.sin_port = htons(portno); // Assign port no to this socket
//Accept a connection from any IP using INADDR_ANY
//You could pass inet_addr("0.0.0.0") instead to accomplish the
//same thing. If you want only to watch for a connection from a
//specific IP, specify that //instead.
addr.sin_addr.s_addr = htonl(INADDR_ANY);
s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // Create a socket
if (s == INVALID_SOCKET)
{
cout << "Couldn't create the socket";
return false; //Don't continue if we couldn't create a //socket!!
}
if (bind(s, (LPSOCKADDR)&addr, sizeof(addr)) == SOCKET_ERROR)
{
//We couldn't bind (this will happen if you try to bind to the same
//socket more than once)
cout << "Error binding the socket";
return false;
}
//Now we can start listening (allowing as many connections as possible to
//be made at the same time using SOMAXCONN). You could specify any
//integer value equal to or lesser than SOMAXCONN instead for custom
//purposes). The function will not //return until a connection request is
//made
listen(s, 1);
reciever = accept(s, NULL, NULL);
cout << "connection established\n\n";
//Don't forget to clean up with CloseConnection()!}
int main(){
e = WSAGetLastError();
listenOnPort(1337, r1, s1);
cout << "First Client connected\n\n";
e = WSAGetLastError();
listenOnPort(1338, r2, s2);
cout << "Second Client connected\n\n";
e = WSAGetLastError();
std::thread com1(communicate, r1, r2);
std::thread com2(communicate, r2, r1);
com1.join();
com2.join();
//system("pause");
closeConnection();}
You have to have 1 thread in the server dedicated to accept new connections.
The process listens to new connections and assigns a new port (in the server) for that connection, making the default port available for new connections.
in the server you will have N+1 socket ports open at any time when N is the number of clients the server has and 1 is the socket listening to new connections.
Take a look at this:
http://www.codeproject.com/Articles/7785/Single-Server-With-Multiple-Clients-a-Simple-C-Imp

Winsock c++ , program freezes on connection to an offline server

My program freezes when trying to connect to an offline server , it doesn't do that if it's online, i know it's trying to connect several times.
is there a way to do that without blocking the main code?
my connection function
bool WSockClient::ConnectServer(int PortNumber, char *IP)
{
SetClientSockAddr(&sockAddr, PortNumber, IP); // Settings
if((hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
return false;
if(connect(hSocket, (sockaddr*)(&sockAddr), sizeof(sockAddr)) != 0) // Connect to the server
return false;
//cout << "Attempting to connect to " << inet_ntoa(sockAddr.sin_addr) << endl;
return true;
}
By default, a socket will be 'blocking', meaning that certain calls (like connect) will block the execution of your program until the operation has been completed. On MS-Windows, you can change the socket to 'non-blocking' using a call to ioctlsocket.
For a non-blocking socket, the connect call will return immediately and you'll have to use select to find out if the connection was successful. You can find some additional info here

bind returns address in use even if no connection is established

I have a c++ code in which I am trying to establish a connection on a socket. But I firstly need to check if a connection already exist on a given port, and if it exists I need to close the connection. I have the code below and my problem is that when checking if the port is already connected it returs that it is even if connect has failed previously.
connected = false;
int sockfd;
void conn(int port) {
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
.....
int sockfd_t;
if ( (sockfd_t = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
cout << "Error opening socket_test " << endl;
return;
}
// check if address already in use
if (bind(sockfd_t, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
if(errno == EADDRINUSE) {
cout << "address in use: bind fail, port=" << port << endl;
}
// do something - close the connection if already connected
}
else {
cout << "bind ok, port=" << port << endl;
}
close(sockfd_t);
if ( (sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
cout << "Error opening socket " << endl;
return;
}
if (connect(sockfd, (struct sockaddr *) &adresse, sizeof(adresse))) {
cout << "Error connecting" << endl;
close(sockfd);
return;
}
connected = true;
}
int main() {
int port=3590;
while (!connected) {
conn(port);
}
cout << "CONNECTED";
// ..........
}
After running the program this is the output printed:
bind ok, port=3590;
Error connecting
bind ok, port=3590;
Error connecting
address in use: bind fail, port=3590 //???
CONNECTED!
I don't know why on the 5-th line of the print it displays "address in use:..." as the connect fails the first two times?
I think you have a misconception about what these socket operations do.
But I firstly need to check if a connection already exist on a given port, and if it exists I need to close the connection.
bind() gives a socket a local address, rather than having anything to do with checking if a remote address you are trying to connect to is accessible.
connect() connects the socket to a remote address.
When connecting a socket as a client (which is what I think you are trying to do), you don't need to check if there is already a connection, remote server can handle multiple incoming client connections to the same port. Binding is usually only important for servers.
if you don't bind before connecting, a socket will be assigned a random local port.
So, if you are a client, you do:
socket()
connect()
If you are a server, you do:
socket()
bind()
listen()
In your own question, the output makes sense when there is no server listening, but then a server comes online.
First two times, you bind a socket and it's successful, because nobody is using it to listen, then you fail to connect, because you just bound, and did not start a server (by calling listen()).
Then a real server on the same host binds that socket and starts listening, therefore you can't bind that port anymore (it fails), but you can connect, because the server is listening.

Winsock2's listen() function finds a connection for every port; even those that don't exist?

I'm attempting to create a method that listens for a connection request to a specific port using a TCP protocol, with no libraries other than those that come with the Windows OS. The method seems to work fine with creating a socket and binding to a port; the problem seems to be with the listen() function. Even with no connection request to any port, it continually returns the value of zero, meaning, straight off of Microsoft's website -
If no error occurs, listen returns zero.
The strange part is that this happens with all port values; it seems to find a connection request for randomly attempted ports, ranging from 1234, to 8000, to -154326. For each of these, it's returning a value of zero.
What it should be doing is continually running until a connection request is found (this is what SOMAXCONN apparently indicates); once again, straight off of Microsoft's website -
If there are no available socket descriptors, listen attempts to continue to function.
Here is the method itself -
bool listenOnPort(SOCKET networkSocket, int portNumber) {
WSADATA wsadata;
int error = WSAStartup(0x0202, &wsadata);
if(error) {
cout << "Failed to start up Windows Sockets API." << endl;
return false;
}
if(wsadata.wVersion != 0x0202) {
WSACleanup();
cout << "Failed to find a valid Windows Sockets API." << endl;
return false;
}
SOCKADDR_IN address;
address.sin_family = AF_INET;
address.sin_port = htons(portNumber);
address.sin_addr.s_addr = htonl(INADDR_ANY);
networkSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(networkSocket == INVALID_SOCKET) {
cout << "Failed to create a network socket." << endl;
return false;
}
if(bind(networkSocket, (LPSOCKADDR)&address, sizeof(address)) == SOCKET_ERROR) {
cout << "Failed to bind to the port." << endl;
return false;
}
cout << "Listening for a connection to port " << portNumber <<"..." << endl;
listen(networkSocket, SOMAXCONN);
cout << "Found a connection!" << endl;
}
Any explanation/word of advice is appreciated - thank you ahead of time!
You've confused listen with accept. listen reserves the port for your application, and queues incoming connections. accept waits for an incoming connection (if one isn't already queued).
listen will succeed when there is no incoming connection attempt.
http://linux.die.net/man/2/listen
listen() marks the socket referred to by sockfd as a passive socket, that is, as a socket that will be used to accept incoming connection requests using accept(2).
You must call "listen()" before you can call "accept()"; but "accept()" is the call that accepts new connections (and gives you a new socket for each new connection).
Here's the man page for "accept()":
http://linux.die.net/man/2/accept
Better, look at Beej's Guide for an excellent introduction to sockets programming:
http://beej.us/guide/bgnet/output/html/multipage/
PS:
And don't forget to call WSAStartup() if you're using Windows sockets :)

Why might bind() sometimes give EADDRINUSE when other side connects?

In my C++ application, I am using ::bind() for a UDP socket, but on rare occasions, after reconnection due to lost connection, I get errno EADDRINUSE, even after many retries. The other side of the UDP connection which will receive the data reconnected fine and is waiting for select() to indicate there is something to read.
I presume this means the local port is in use. If true, how might I be leaking the local port such that the other side connects to it fine? The real issue here is that other side connected fine and is waiting but this side is stuck on EADDRINUSE.
--Edit--
Here is a code snippet showing that I am already doing SO_REUSEADDR on my TCP socket, not on this UDP socket for which I am having issue:
// According to "Linux Socket Programming by Example" p. 319, we must call
// setsockopt w/ SO_REUSEADDR option BEFORE calling bind.
// Make the address is reuseable so we don't get the nasty message.
int so_reuseaddr = 1; // Enabled.
int reuseAddrResult
= ::setsockopt(getTCPSocket(), SOL_SOCKET, SO_REUSEADDR, &so_reuseaddr,
sizeof(so_reuseaddr));
Here is my code to close the UDP socket when done:
void
disconnectUDP()
{
if (::shutdown(getUDPSocket(), 2) < 0) {
clog << "Warning: error during shutdown of data socket("
<< getUDPSocket() << "): " << strerror(errno) << '\n';
}
if (::close(getUDPSocket()) < 0 && !seenWarn) {
clog << "Warning: error while closing data socket("
<< getUDPSocket() << "): " << strerror(errno) << '\n';
}
}
Yes, that's normal. You need to set the socket SO_REUSEADDR before you bind, eg on *nix:
int sock = socket(...);
int yes = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
If you have separate code that reconnects by creating a new socket, set it on that one too. This is just to do with the default behaviour of the OS -- the port on a broken socket is kept defunct for a while.
[EDIT] This shouldn't apply to UDP connections. Maybe you should post the code you use to set up the socket.
In UDP there's no such thing as lost connection, because there's no connection. You can lose sent packets, that's all.
Don't reconnect, simply reuse the existing fd.