Winsock binding on the same port - c++

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

Related

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

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.

C++ WINSOCK tcpaccept stops accepting connections after an "attack"

I have a game server in C++ and I'm using a network library that uses winsock in Windows.
I've been stress-testing my server to see how many connections it can accept at a time. It works fine when I connect using my game clients but my game clients can no longer connect after I do a stress-test described below.
The stress test is, I connected to my server about 1000 times using a simple program for loop that just starts a tcp connection with my game server and closes it right away. They all connect. Then, after, I try to connect with my game. The game does not connect at all.
I checked the tcpaccept() function from the library (see below), no output. For some reason, accept() stops accepting connections after my "attack" of 1000 connections.
What could possibly make my server just stop accepting connections?
Here's my summary of my loop that listens and accepts connections and closes them:
bool serverIsOn = true;
double listen = tcplisten(12345, 30000, 1);
setnagle(listen, true);
...
while(serverIsOn){
double playerSocket = tcpaccept(listen, 1);
if(playerSocket > -1){
cout << "Got a new connection, socket ID: " << playerSocket << endl;
//add their sockID to list here!
addSockIDToList(playerSocket);
}
//Loop through list of socks and parse their messages here..
//If their message size == 0, we close their socket via closesocket(sockID);
loopThroughSocketIdsAndCloseOnLeave();
}
cout << "Finished!" << endl;
Here's the definitions for tcplisten, tcpaccept, CSocket::CSocket(SOCKET), CSocket::tcplisten(...) and CSocket::tcpaccept(...):
double tcplisten(int port, int max, int mode)
{
CSocket* sock = new CSocket();
if(sock->tcplisten(port, max, mode))
return AddSocket(sock);
delete sock;
return -1;
}
double tcpaccept(int sockid, int mode)
{
CSocket*sock = (CSocket*)sockets.item(sockid);
if(sock == NULL)return -1;
CSocket*sock2 = sock->tcpaccept(mode);
if(sock2 != NULL)return AddSocket(sock2);
return -1;
}
...
CSocket::CSocket(SOCKET sock)
{
sockid = sock;
udp = false;
format = 0;
}
bool CSocket::tcplisten(int port, int max, int mode)
{
if((sockid = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) return false;
SOCKADDR_IN addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(port);
if(mode)setsync(1);
if(bind(sockid, (LPSOCKADDR)&addr, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
{
closesocket(sockid);
return false;
}
if(listen(sockid, max) == SOCKET_ERROR)
{
closesocket(sockid);
sockid = INVALID_SOCKET;
return false;
}
return true;
}
CSocket* CSocket::tcpaccept(int mode)
{
if(sockid == INVALID_SOCKET) return NULL;
SOCKET sock2;
if((sock2 = accept(sockid, (SOCKADDR *)&SenderAddr, &SenderAddrSize)) != INVALID_SOCKET)
{
//This does NOT get output after that 1000-'attack' test.
std::cout << "Accepted new connection!" << std::endl;
CSocket*sockit = new CSocket(sock2);
if(mode >=1)sockit->setsync(1);
return sockit;
}
return NULL;
}
What can I do to figure out why accept() no longer accepts connections after my 1000-connection stress test? Does it have something to do with the way I close connections after their finished? When I do that, all I do is just call: closesocket(sockID).
Please ask for any other code needed!
EDIT:
I just noticed that my "stress-test" java program is getting an exception after its connected around 668 times. Here's the exception:
Exception in thread "main" java.net.ConnectException: Connection refused: connect
at java.net.DualStackPlainSocketImpl.connect0(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:579)
at java.net.Socket.connect(Socket.java:528)
at java.net.Socket.<init>(Socket.java:425)
at java.net.Socket.<init>(Socket.java:208)
at sockettest.SocketTest.main(SocketTest.java:63)
Java Result: 1
Because your server side is closing the sockets, they are most likely sitting in time_wait for several minutes. Windows has various parameters controlling maximum sockets and various states. I am guessing your program starts working again after several minutes, and potentially there are some warnings in event viewer.
An alternative might be to simply ignore these sockets for several minutes and hope they go away. ie the client calls closesocket when you dont respond at all, which means you do not incur time_wait. This often works but not always. If they do not, then you call closesocket() slowly on them in the background.
If you really want too though, you can reset the connection, see TCP option SO_LINGER (zero) - when it's required for details, but reseting connections is not normal so definitely read widely about So_linger and how tcp teardown works.
It turns out this library has it's own method of closing a socket:
int closesock(int sockid)
{
CSocket*sock = (CSocket*)sockets.item(sockid);
if(sock == NULL)return -1;
delete sock;
sockets.set((int)sockid, NULL);
return 1;
}
So it gets the current socket via the sockID in the list of sockets.
Then if the sockID was related to a valid socket, delete the sock object and set it to NULL in the list of sockets.
The problem was I was only calling closesocket(sockID) instead of closesock(sockID) which performed the necessary operations needed to close a socket.
Thanks everyone for your help.

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.

Client connects to server but server does not think client has connected in C++

I have a C++ program, using mpi, that follows a typical client server model. Each mpi instance of the client connects to a corresponding mpi instance of the server. This has worked relatively well until I have had to do some testing with added latency (1 second of added latency to be precise).
Problem:
Sometimes one of the server processes do not think the client has connected but the client thinks it has connected. i.e. After using gdb, the server is waiting at accept() but the client has continued on past connect(). Thus, it appears the client thinks it has connected when the server does not think it has connected.
My best guess is that I need to set an sock-option somewhere, however talking to fellow programmers and googling has not yielded any helpful results.
EDIT:
There are two sets of MPI processes (so two different calls to mpirun), the accept() and connect() calls are for the sockets, which are between the two sets of MPI processes. It is openmpi.
The code (from someone else's code, actually) [reduced]:
Client (connect code): (m_socket is the actual socket)
if (-1 == m_socket)
{
perror("cannot create socket");
exit(EXIT_FAILURE);
}
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
res = inet_pton(AF_INET, host_ip, &addr.sin_addr);
if (0 > res)
{
perror("error: first parameter is not a valid address family");
close(m_socket);
exit(EXIT_FAILURE);
}
else if (0 == res)
{
perror("error: second parameter does not contain valid IP address");
close(m_socket);
exit(EXIT_FAILURE);
}
//backoff
for (int sec = 1; sec < 20000; sec++ )
{
int ret;
if (0 == (ret = connect(m_socket, (struct sockaddr *)&addr, sizeof(addr))))
{
return;
}
sleep(1);
close(m_socket);
m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
}
perror("connect failed");
close(m_socket);
exit(EXIT_FAILURE);
Server: (m_socket is the actual socket)
int socket = ::accept(m_socket, NULL, NULL);
if(socket < 0)
{
fprintf(stderr, "accept() failed: %s\n", strerror(errno));
close(m_socket);
exit(EXIT_FAILURE);
}
It looks like you're trying to do your connect/accept manually rather than with MPI. You might take a look at the example on Deino (http://mpi.deino.net/mpi_functions/MPI_Comm_accept.html) if you're trying to use MPI for your connections.
Alternatively, you might just need to look at a more general tutorial (some available here: http://www.mcs.anl.gov/research/projects/mpi/tutorial/) of MPI to get a feel for how communication works. Most of the time and application doesn't use Connect/Accept to communicate, but uses MPI Communicators to set up communication mechanisms between processes. It's a different model (SPMD as opposed to MPMD).

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 :)