Skip to main content
gamedev.net
🔒 Locked

WSAECONNRESET error

Started by swilkewitz 13 replies 4.3k views
Original Post
swilkewitz
swilkewitz
I recently started teaching myself network programming; I've been using this tutorial: http://www.madwizard.org/programming/tutorials/netcpp/7
So I followed the section on creating a basic blocking server, and everything works except for a WSAECONNRESET error. I ran the source code available to download and that didn't work either. I've done a little bit of research on this error, and it sounds like there are a lot of causes. I'm not sure what information would be useful for you guys, so just ask if you need something.

Thanks,
Scott

#include <iostream>
#include <string>
#include <sstream>
#include <winsock2.h>
#include <windows.h>
using namespace std;

class ROTException
{
public:
ROTException() :
m_pMessage("") {}
virtual ~ROTException() {}
ROTException(const char *pMessage) :
m_pMessage(pMessage) {}
const char *what(){ return m_pMessage;}

private:
const char *m_pMessage;
};

const int REQ_WINSOCK_VER = 2;
const int DEFAULT_PORT = 4444;
const int TEMP_BUFFER_SIZE = 128;

//Bind Socket
void setServerSockAddr(sockaddr_in *pSockAddr, int portNumber)
{

pSockAddr->sin_family = AF_INET;
pSockAddr->sin_port = htons(portNumber);
pSockAddr->sin_addr.S_un.S_addr = INADDR_ANY;
}

//Return string about host
string getHostDescription(const sockaddr_in &sockAddr)
{

ostringstream stream;
stream << inet_ntoa(sockAddr.sin_addr) << ":" << ntohs(sockAddr.sin_port);
return stream.str();
}

void rot13(char *pBuffer, int size)
{
for(int i=0;i<size;i++)
{
char c = pBuffer;
if ((c >= 'a' && c < 'n') || (c >= 'A' && c < 'N') )
c += 13;
else if ((c>='n' && c <= 'z') || (c>='N' && c <= 'Z'))
c -= 13;
else
continue;
pBuffer = c;
}
}

//Handle Clients
void handleConnection(SOCKET hClientSocket, const sockaddr_in &sockAddr)
{

cout << "Connected with " << getHostDescription(sockAddr) << ".\n";
char tempBuffer[TEMP_BUFFER_SIZE];

//Interact with Client
while(true){

int retval;
retval = recv(hClientSocket, tempBuffer, sizeof(tempBuffer), 0);

if(retval == 0)
break;

else if(retval == SOCKET_ERROR){ //This is where the error occurs. I have allowed the program to continue.
if(WSAGetLastError() != WSAECONNRESET)
throw ROTException("Socket error #1 while receiving.");

}else{

rot13(tempBuffer, retval);
if(send(hClientSocket, tempBuffer, retval, 0) == SOCKET_ERROR)
throw ROTException("Socket error #2 while sending.");
}
}

cout << "Connection close.\n";
}

//Setup Sockets
bool runServer(int portNumber)
{

SOCKET hSocket = INVALID_SOCKET, hClientSocket = INVALID_SOCKET;
bool bSuccess = true;
sockaddr_in sockAddr = {0};

try{

//Create Socket
cout << "Creating socket... ";
if((hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
throw ROTException("Could not create socket.");
cout << "created.\n";

//Bind Socket
cout << "Binding socket... ";
setServerSockAddr(&sockAddr, portNumber);
if(bind(hSocket, reinterpret_cast<sockaddr*>(&sockAddr), sizeof(sockAddr)) != 0)
throw ROTException("Could not bind socket.");
cout <<"bound.\n";
cout << getHostDescription((const sockaddr_in)sockAddr);

//Listen
cout << "Putting socket in listening mode... ";
if(listen(hSocket, SOMAXCONN)!= 0)
throw ROTException("Could not put socket in listening mode.");
cout << "ready.\n";

//Connect
cout << "listening... ";
sockaddr_in clientSockAddr;
int clientSockSize = sizeof(clientSockAddr);
hClientSocket = accept(hSocket, reinterpret_cast<sockaddr*>(&clientSockAddr), &clientSockSize);
if(hClientSocket == INVALID_SOCKET)
throw ROTException("Accept function failed.");
cout << "Client found.\n";

//Handle Connection
handleConnection(hClientSocket, clientSockAddr);

}catch(ROTException e){
cerr << "\nError: " << e.what() << endl;
bSuccess = false;
}
}

//Main
int main(int argc, char *argv[])
{

int iRet = 1;
WSADATA wsaData;

cout << "Initializing winsock... ";

if(WSAStartup(MAKEWORD(REQ_WINSOCK_VER, 0), &wsaData) == 0){

if(LOBYTE(wsaData.wVersion) >= REQ_WINSOCK_VER){

cout << "initialized.\n";

int port = DEFAULT_PORT;
if(argc > 1)
port = atoi(argv[1]);
iRet = !runServer(port);
}else
cerr << "required version not supported!";

cout << "Cleaning up winsock... ";

if(WSACleanup() != 0){
cerr << "cleanup failed!\n";
iRet = 1;
}

cout << "done.\n";
}else
cerr << "startup failed!\n";

while(1){}
return iRet;
}




swilkewitz
swilkewitz
The client is a downloadable program called putty, which I am running on the same machine. I am using localhost for the hostname, 4444 for the port and Raw for the connection type.
Drew_Benton
Drew_Benton
Please elaborate the problem more. Include as much information as possible. What steps do you take to trigger the error and is it repeatable. What operating system (is it x64 or x86) are you using? I ran the code fine with no errors and everything worked as expected for one connection coming from putty and telnet.

While the code design itself needs more work, I didn't encounter the error you mentioned.
swilkewitz
swilkewitz
Thanks for the reply Drew!

My OS is Windows 7, 64-bit. The problem always occurs as soon as putty connects. Everything goes smoothly until the server tries to recv() from putty, that is when it gets the error. I don't think that Putty actually sends anything to the server, so I don't understand why an error would occur.
I will probably write my own client later today so that I have more control.
Drew_Benton
Drew_Benton
That's exactly my setup as well. With putty and the raw connection, you have to type stuff then hit enter to send. If you use telnet instead, it will send as you type. Using putty as a simple client program is actually better to test with rather than your own client at first because you know that the client works so any problems you have will be on the server. I compiled your example with VS2010 as well as VS2008 and it worked.

As to why you are getting an exception on connect, I'm not too sure. However, my educated guess is that it has to do something with your firewall, antivirus, or UAC controls. Upon running the server, I had to "Allow acccess" for the program because Windows Firewall popped up. If you didn't allow it or have some 'limited' access setting for it, it's possible it will not be able to receive connections since Windows might think it's a malware threat. Also, consider your access privileges of the account you are on. You can try running as Admin if you are not already, since sometimes, certain API calls end up needing it. The account I'm running on is an Admin, but I still have UAC enabled.

So check all your security settings, any protection programs, and so on because I think your problem right now has to do with that rather than the actual code. I'm only running Windows Firewall and Microsoft Security Essentials on an Admin account with UAC enabled (but screen dim disabled since it's so annoying) .
swilkewitz
swilkewitz
Yeah, I thought that might be the problem, so I checked the firewall earlier and allowed my program (and Putty) through. My account isn't an admin, so I will see if that is the problem when I get home.

Thanks!
hplus0603
hplus0603

I recently started teaching myself network programming; I've been using this tutorial: http://www.madwizard...orials/netcpp/7

if(WSAStartup(MAKEWORD(REQ_WINSOCK_VER, 0), &wsaData) == 0){



That code makes me distrust the tutorial in general. WinSock 2.2 is the version everyone should be using since it came out, which is over 15 years ago IIRC.

Unfortunately, many tutorials on the web are written by people as a way for themselves to learn something, or within their first year or two after learning something, when they haven't really gotten to the level of understanding and best practices that you'd want to have in a reference used by other people.
enum Bool { True, False, FileNotFound };
swilkewitz
swilkewitz
Ok, so I've been able to do some testing... My computer uses Norton Antivirus, Windows Firewall, and Safe Eyes. Normally I do my testing in our family account, but this time I used the admin account on our computer. I disabled Windows Firewall and Safe Eyes, and I added the locations of both my server and Putty to Norton's bypass list. As far as I know, there is no way to completely disable Norton. Anyway, I ran my server, then I ran Putty with the same settings as always. Unfortunately, I still got the same error. I will run a system update, just in case. <BR><BR>Edit: When I set Putty's "Close window on exit" option to "never" then I get two errors from Putty:<BR>Connection close by remote host<BR>Network error: Connection refused
swilkewitz
swilkewitz
I tried using some sample code from another tutorial which worked perfectly...
http://www.tidytutorials.com/2009/12/c-winsock-example-using-client-server.html

So the problem was either with the old tutorial, or with Putty.
Anyway, next I am going to write a very basic IM program and attempt to communicate between multiple machines. I will probably start from scratch and use this new tutorial as a reference if I need it.

Thanks for the help!
Scott Wilkewitz
Antheus
Antheus
or with Putty.


Just like guest is always right, the client is also always right.

So whatever bugs or other issues any given client has, the server needs to handle them. Putty, being almost de-facto telnet/ssh client, is likely to be quite well-behaved compared to alternatives

This is one argument for using popular/standard servers. Apache (and others) still contain #ifdefs and configuration settings for various broken network stacks, OS oddities, client inconsistencies.

It's also an argument for using a standard and widely available networking stacks. Either boost or ACE for C++ or better yet, a language with networking, perhaps even HTTP as part of core standard library. Either the library will be high enough quality or other clients and peers will have workarounds due to widespread use of possibly "broken" servers.
hplus0603
hplus0603

Anyway, next I am going to write a very basic IM program and attempt to communicate between multiple machines. I will probably start from scratch and use this new tutorial as a reference if I need it.


If you want to build a simple chat/IM server that scales to thousands of users, I recommend using node.js. Writing a simple IM or chat system is really easy within that environment, as long as you don't need to scale beyond a single server machine!

If you want to build a real chat/IM service that scales to millions of users, I recommend using Erlang.OTP. (Well, at least that's what I used, and I liked it)
enum Bool { True, False, FileNotFound };
swilkewitz
swilkewitz
Right now I am just trying to learn the basics. I also like to go bare-bones and do everything from scratch; I don't like using libraries to skip steps. I am making an IM service just to see if I can network between two local machines. Anyway, I made my own server and it works using a mix of the two tutorials. Next I'm going to make my own client to go along with my server.

My goal is to implement LAN multiplayer into a game I'm making.

Thanks!
Scott

swilkewitz
swilkewitz
I finished making my client and I have noticed some odd behavior. I have allowed the server to take as many clients as it wants, which means if the server drops a client then the client can try again.

First, my server can't send messages on the first attempted connection of its "life". Putty automatically retries, but my client must be rerun.
Second, my server can send messages on any subsequent connection.
Third, both clients can always send messages to the server flawlessly, but Putty reconnects too fast to type anything the first time around.
Fourth, each time I attempt to connect using putty, it takes two attempts to connect successfully, with the first attempt resulting in the WSAECONNRESET error.
Fifth, I get that error every time I close my own client.
Sixth, if I allow the server to continue receiving messages after an error, then once I close my own client it continues to receive the last message infinitely.

Here is some code:

Client:
#include <winsock2.h>
#include <windows.h>
#include <iostream>
#include <string.h>
#include <sstream>
using namespace std;

int port = 4444;
char* name = "127.0.0.1";

WSADATA wsaData;
int hsock;

const int buffer_length = 128;
bool done = false;

//Send Messages to server
DWORD WINAPI sendMessages(void* lp)
{

//IM Send Loop
while(1){
//Get Input
string s;
getline(cin, s);

//Exit?
if(s == "exit"){
done = true;
break;
}

//Append New Line
s += "\n";

//Send Message to All
if(hsock != INVALID_SOCKET){
if(send(hsock, s.c_str(), s.length(), 0) == SOCKET_ERROR && WSAGetLastError() != 10038 && WSAGetLastError() != 10054)
cout << "socket error while sending. Error: " << WSAGetLastError();
}else
cout << "Not Connected, retry.\n";
}

return 0;
}

//Set Up Listener
void runClient()
{

//Set up sockAddr
sockaddr_in sockAddr;
sockAddr.sin_family = AF_INET;
sockAddr.sin_port = htons(port);
sockAddr.sin_addr.S_un.S_addr = inet_addr(name);

//Create
cout << "Creating socket... ";
if ((hsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
cout << "could not create socket. Error: " << WSAGetLastError();
else cout <<"created.\n";

//Connect
cout << "Connecting to server... ";
if(connect(hsock, (struct sockaddr*)&sockAddr, sizeof(sockAddr)) == SOCKET_ERROR)
cout << "could not connect to server. Error: " << WSAGetLastError();
else cout <<"Connected.\n";

//Receive Messages
if(hsock != INVALID_SOCKET){
while(!done){

int size;
char buffer[buffer_length];

//Get Message
size = recv(hsock, buffer, buffer_length, 0);

if(size == 0)
break;
else if(size == SOCKET_ERROR){
cout << "socket error while receiving. Error: " << WSAGetLastError() << "\nThe connection may be recovered...\n";
break;

}else{

//Print Message
buffer[size] = '\0';
cout << buffer;
}
}
}
}

int main(int argc, char** argv)
{

//Send Messages
CreateThread(0, 0, &sendMessages, NULL, 0, 0);

//Start Winsock
cout << "Initializing winsock... ";
if(WSAStartup(MAKEWORD(2, 2), &wsaData) == 0){
if(LOBYTE(wsaData.wVersion) >= 2 && HIBYTE(wsaData.wVersion) >= 2){
cout << "initialized.\n";
if(argc > 1)
port = atoi(argv[1]);

//Create, Connect Socket
runClient();

}else cout << "required version not supported! Error: " << WSAGetLastError();
}else cout << "Startup failed! Error: " << WSAGetLastError();

//Cleanup
cout << "Cleaning up winsock... ";
//Server Sockets
closesocket(hsock);
//Cleanup
if(WSACleanup()!= 0){
cout << "cleanup failed! Error: " << WSAGetLastError();
}else cout << "done.\n";

return 0;
}


Server:
#include <winsock2.h>
#include <windows.h>
#include <iostream>
#include <string.h>
#include <sstream>
using namespace std;

int port = 4444;
WSADATA wsaData;
SOCKET listenSocket = INVALID_SOCKET;
sockaddr_in clientSockAddr;
int clientSockSize;
int* clientSock[6];
int numClients = 0;
const int buffer_length = 128;
bool done = false;

//Receive Messages From Clients
DWORD WINAPI receiveMessages(void* lp)
{

int *cs = (int*)lp;

cout << "New connection made.\n";
while(!done){
int size;
char buffer[buffer_length];

//Get Message
size = recv(*cs, buffer, buffer_length, 0);

if(size == 0)
break;
else if(size == SOCKET_ERROR){
cout << "socket error while receiving. Error: " << WSAGetLastError() << "\nThe connection may be recovered...\n";
break;

}else{

//Print Message
buffer[size] = '\0';
cout << buffer;
}
}

return 0;
}

//Send Messages to Clients
DWORD WINAPI sendMessages(void* lp)
{

//IM Send Loop
while(1){
//Get Input
string s;
getline(cin, s);

//Exit?
if(s == "exit"){
done = true;
break;
}

//Append New Line
s += "\n";

//Send Message to All
for(int i = 1; i < numClients; i++){

if(*clientSock != INVALID_SOCKET){
if(send(*clientSock, s.c_str(), s.length(), 0) == SOCKET_ERROR && WSAGetLastError() != 10038 && WSAGetLastError() != 10054)
cout << "socket error while sending. Error: " << WSAGetLastError();
}else
cout << "Not Connected, retry.\n";
}
}

return 0;
}

//Get New Clients
DWORD WINAPI listen(void* lp)
{

while(!done){

//Accept Connection
clientSock[numClients] = (int*)malloc(sizeof(int));
*clientSock[numClients] = accept(listenSocket, reinterpret_cast<sockaddr*>(&clientSockAddr), &clientSockSize);

//Serve Client
if(*clientSock[numClients] != INVALID_SOCKET)
CreateThread(0, 0, &receiveMessages, (void*)clientSock[numClients], 0, 0);

numClients++;
}

return 0;
}

//Set Up Listener
void runServer()
{

sockaddr_in sockAddr = {0};

//Create
cout << "Creating socket... ";
if ((listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
cout << "could not create socket. Error: " << WSAGetLastError();
else cout <<"created.\n";

//Set up sockAddr
cout << "Binding socket... ";
sockAddr.sin_family = AF_INET;
sockAddr.sin_port = htons(port);
sockAddr.sin_addr.S_un.S_addr = INADDR_ANY;

//Bind
if(bind(listenSocket, reinterpret_cast<sockaddr*>(&sockAddr), sizeof(sockAddr)) != 0)
cout << "could not bind socket. Error: " << WSAGetLastError();
else cout <<"bound.\n";

//Listen
cout << "Entering listen mode... ";
if(listen(listenSocket, SOMAXCONN) != 0)
cout << "could not enter listen mode. Error: " << WSAGetLastError();
else cout <<"Listening.\n";

//Get Clients
clientSockSize = sizeof(clientSockAddr);
CreateThread(0, 0, &listen, NULL, 0, 0);
}

int main(int argc, char** argv)
{

CreateThread(0, 0, &sendMessages, NULL, 0, 0);

//Start Winsock
cout << "Initializing winsock... ";
if(WSAStartup(MAKEWORD(2, 2), &wsaData) == 0){
if(LOBYTE(wsaData.wVersion) >= 2 && HIBYTE(wsaData.wVersion) >= 2){
cout << "initialized.\n";
if(argc > 1)
port = atoi(argv[1]);

//Create, Bind, Listen, Accept Socket
runServer();

}else cout << "required version not supported! Error: " << WSAGetLastError();
}else cout << "Startup failed! Error: " << WSAGetLastError();

while(!done){}

//Cleanup
cout << "Cleaning up winsock... ";
//Client Sockets
for(int i = 0; i < numClients; i++){
closesocket(*clientSock);
free(clientSock);
}
//Server Socket
if(listenSocket != INVALID_SOCKET)
closesocket(listenSocket);

//Cleanup
if(WSACleanup()!= 0){
cout << "cleanup failed! Error: " << WSAGetLastError();
}else cout << "done.\n";

return 0;
}


hplus0603
hplus0603

First, my server can't send messages on the first attempted connection of its "life". Putty automatically retries, but my client must be rerun.

while(!done){}



This code is really, really bad. It will busy wait, which on a single-core machine may actually starve out other processes. The minimum you should do is to Sleep(10) or something like that. However, it would be much better to actually run the server loop in that while() statement instead of on its own thread.
Also, you shouldn't be trying to use threads right now. You're trying to learn distributed programming, which is hard enough without adding synchronization and in-core concurrency to the mix.
Use select() to multiplex between the sockets (your listening socket, plus any connected sockets). The FAQ (linked at the top of the forum) has several good links and descriptions about how to set up these things.
enum Bool { True, False, FileNotFound };
swilkewitz
swilkewitz
Ok, thanks! I'll look into that.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.