C++ Winsock Connecting to an IP Address Problem

Started by
11 comments, last by codyrigney92 12 years, 1 month ago
So i finished the networking code on the same machine (the client connects to IP 127.0.0.1), and it works perfectly, but then when i tried giving it the another person, it didnt connect. i was wondering if the ip on the machine can be used to connect... also, we use hamachi, so when i gave him that ip it still didnt work. is there something i need to know about connecting different machines? PS: im using TCP sockets.
Advertisement
EDIT:

What im trying to say is that it works on a local machine, but not on separate computers.
Perhaps some code showing how you initialise it will help?
However, this belongs in the Multiplayer and Networking section :)
Sorry, whoops. :-\

What do you mean by initializing?

ServerStats.h:
#include <string>
#include <vector>
#include <Winsock2.h>
#include <Windows.h>
class Client_Sock
{
public:
SOCKET mSock;
std::string Ip;
unsigned int Id,Ping,ThreadKillState;
bool OK;
HANDLE mThread;
void New(SOCKET nSock,std::string nIp,unsigned int nID);
void Die();
};
class ServerStats
{
public:
bool Host,Connected,Connecting;
std::vector<Client_Sock> ConnectedIPs;
SOCKET MySocket;
WSADATA nData;
SOCKADDR_IN Target;//Socket address information
std::string DefaultIP,IPConnectedTo;
int DefaultPort,PortConnectedTo;
HANDLE mThread;
unsigned int Ping,ThreadKillState,LastSecond;

void Init(bool nHost);
void Restart();
void Quit();
unsigned int ErrorID;

bool LastError(std::string What);
void Connect(std::string nHost,int Port);
void DisConnect();
void Listen(int PortNO);
void Send(std::string What,int Who);
void HandleMessage(std::string Mess,std::string Plr);
void CheckPings();
void Kill_Sock(unsigned int Sock);

unsigned int ReadyToStartGame;
};
DWORD WINAPI ListenForNew(void*);
DWORD WINAPI HandleNewConnection(void*);
DWORD WINAPI ConnectToHost(void*);


ServerStats.cpp:
#include "ServerStats.h"
#include "App.h"
extern myApp APP;
#include "Functions.h"
#define REC_MAX 1024
void Client_Sock::New(SOCKET nSock,std::string nIp,unsigned int nID)
{
Client_Sock::mSock=nSock;
Client_Sock::Ip=nIp;
Client_Sock::Id=nID;
Client_Sock::OK=true;
Client_Sock::Ping=0;
Client_Sock::ThreadKillState=0;//None
unsigned int nErr=WSAGetLastError();
if(nErr!=0)
{
LPTSTR Error=0;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,NULL,nErr,0,(LPTSTR)&Error,0,NULL);
std::stringstream nError;nError<<"WSA Sync Socket Error: "<<nErr<<", "<<Error;
APP.ServerLog.Write((nError.str()).c_str());
}
Client_Sock::mThread=CreateThread(NULL,0,HandleNewConnection,(void*)nID,0,NULL);
}
void Client_Sock::Die()
{
Client_Sock::OK=false;
Client_Sock::ThreadKillState=1;
TerminateThread(Client_Sock::mThread,0);
closesocket(Client_Sock::mSock);
}
void ServerStats::Init(bool nHost)
{
unsigned int nErr=WSAStartup(MAKEWORD(2,2),&this->nData);
if(nErr!=0)
{
LPTSTR Error=0;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,NULL,nErr,0,(LPTSTR)&Error,0,NULL);
std::stringstream nError;nError<<"WSA Startup Error: "<<nErr<<", "<<Error;
APP.ServerLog.Write((nError.str()).c_str());
}
ServerStats::DefaultIP="5.14.221.173";
ServerStats::DefaultPort=31316;
ServerStats::Host=nHost;
this->LastSecond=APP.LastSecond;
this->ErrorID=0;
this->ReadyToStartGame=0;
ServerStats::MySocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(this->LastError("Socket"))
{
this->DisConnect();
}
ServerStats::Connected=false;
ServerStats::Connecting=false;
}
void ServerStats::Restart()
{
this->LastSecond=APP.LastSecond;
ServerStats::MySocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(this->LastError("Socket"))
{
this->DisConnect();
}
ServerStats::Connected=false;
ServerStats::Connecting=false;
}
void ServerStats::Quit()
{
if(this->Connected || this->Connected)
{
this->DisConnect();
}
closesocket(ServerStats::MySocket);
WSACleanup();
}
bool ServerStats::LastError(std::string What)
{
this->ErrorID=WSAGetLastError();
if(this->ErrorID!=0)
{
LPTSTR Error=0;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,NULL,this->ErrorID,0,(LPTSTR)&Error,0,NULL);
std::stringstream nError;nError<<What+" Error: "<<this->ErrorID<<", "<<Error;
APP.ServerLog.Write((nError.str()).c_str());
return true;
}
else
{
return false;
}
}
#include "App.h"
extern myApp APP;
#include "GameStats.h"
extern GameStats Game;
extern ServerStats Server;
#include "ScreenClass.h"
extern Screen MainScreen;
void ServerStats::Connect(std::string nHost,int Port)
{
if(!this->Host && !this->Connected && !this->Connecting)//first
{
this->Restart();
this->Connecting=true;
this->IPConnectedTo=nHost;
this->PortConnectedTo=Port;
ServerStats::Target.sin_family=AF_INET;
ServerStats::Target.sin_port=htons(Port);
ServerStats::Target.sin_addr.s_addr=inet_addr(nHost.c_str());
if(this->mThread==NULL)//Have not started thread
{
this->mThread=CreateThread(NULL,0,ConnectToHost,(void*)NULL,0,NULL);
}
}
else if(!this->Host && this->Connecting && !this->Connected)
{
connect(this->MySocket,(SOCKADDR*)&Target,sizeof(ServerStats::Target));
if(!this->LastError("Connect"))//no error
{
this->Connected=true;
this->Connecting=false;

newHuman Host;Host.Init(0,0,0,"client",0,"client",0,0,0);
Game.OnlinePlrs.push_back(Host);
if(this->ReadyToStartGame==0){this->ReadyToStartGame=1;}
}
}
else if(this->Host)
{
APP.ServerLog.Write("Tried To Connect When A Host");
}
else
{
APP.ServerLog.Write("Tried To Connect When Already Connected");
}
}
void ServerStats::DisConnect()
{
shutdown(this->MySocket,SD_SEND);
if(this->Host)
{
for(unsigned int s=0;s<ServerStats::ConnectedIPs.size();s++)
{
ServerStats::Kill_Sock(s);
}
ServerStats::ConnectedIPs.clear();
}
else//not a host
{
ServerStats::ThreadKillState=1;//Class stuff
}
TerminateThread(this->mThread,0);
this->mThread=NULL;
this->Connected=false;
this->Connecting=false;
this->IPConnectedTo="0.0.0.0";
this->Ping=0;
this->PortConnectedTo=0;
this->ThreadKillState=0;
this->ErrorID=0;
}
void ServerStats::Listen(int PortNO)
{
if(this->Host && !this->Connected)
{
this->Restart();
this->Connected=true;
ServerStats::Target.sin_family=AF_INET;
ServerStats::Target.sin_port=htons(PortNO);//assign port to this socket
ServerStats::Target.sin_addr.s_addr=inet_addr("127.0.0.1");
bind(ServerStats::MySocket,(LPSOCKADDR)&this->Target,sizeof(ServerStats::Target));
listen(this->MySocket,1);
if(this->mThread==NULL)//Have not started thread
{
this->mThread=CreateThread(NULL,0,ListenForNew,(void*)NULL,0,NULL);
}
}
else if(!this->Host)
{
APP.ServerLog.Write("Tried To Listen When NOT A Host");
}
else if(this->Connected)
{
APP.ServerLog.Write("Tried To Listen When Listening");
}
}
void ServerStats::Send(std::string What,int Who)
{
if(ServerStats::Host)
{
if(Who==-1)//All clients
{
for(unsigned int s=0;s<ServerStats::ConnectedIPs.size();s++)
{
send(ServerStats::ConnectedIPs[s].mSock,What.c_str(),What.size(),0);
}
}
else if((unsigned int)Who<ServerStats::ConnectedIPs.size())
{
send(ServerStats::ConnectedIPs[Who].mSock,What.c_str(),What.size(),0);
}
}
else
{
send(ServerStats::MySocket,What.c_str(),What.size(),0);
}
}
void ServerStats::HandleMessage(std::string Mess,std::string Plr)
{
std::vector<std::string>mParts;
unsigned int State=0;
std::string Buf;
if(this->Host)
{
unsigned int PlrID=0;//No id
/*for(unsigned int nPlr=0;nPlr<Game.OnlinePlrs.size();nPlr++)
{
if(Game.OnlinePlrs[nPlr].Brain.Name==Plr)
{
PlrID=nPlr+1;
nPlr=Game.OnlinePlrs.size();
}
}*/
if(Game.OnlinePlrs.size()>0){PlrID=1;}
if(PlrID!=0)
{
PlrID--;
for(unsigned int l=0;l<Mess.length();l++)
{
if(State==5)
{
l=Mess.length();
}
else if(Mess[l]==',' || Mess[l]=='\\')
{
switch(State)
{
case 0:Game.OnlinePlrs[PlrID].myX=(float)atof(Buf.c_str());break;
case 1:Game.OnlinePlrs[PlrID].myY=(float)atof(Buf.c_str());break;
case 2:Game.OnlinePlrs[PlrID].myZ=(float)atof(Buf.c_str());break;

case 3:Game.OnlinePlrs[PlrID].RotX=(float)atof(Buf.c_str());break;
case 4:Game.OnlinePlrs[PlrID].RotY=(float)atof(Buf.c_str());break;
}
State++;
Buf.clear();
}
else
{
Buf+=Mess[l];
}
}
}
}
else
{
}
}
void ServerStats::CheckPings()
{
for(unsigned int s=0;s<ServerStats::ConnectedIPs.size();s++)
{
if(ServerStats::ConnectedIPs[s].Ping>10000)
{
ServerStats::Kill_Sock(s);
}
}
}
void ServerStats::Kill_Sock(unsigned int Sock)
{
if(Sock<ServerStats::ConnectedIPs.size())
{
ServerStats::ConnectedIPs[Sock].Die();
//Ready for class removal
ServerStats::ConnectedIPs.erase(ServerStats::ConnectedIPs.begin()+Sock);
}
}
DWORD WINAPI ListenForNew(void* LOL)
{
while(Server.ThreadKillState==0)
{
Client_Sock AcceptSock;
sockaddr_in nAddr;int nLength=sizeof(nAddr);
SOCKET defAccept=accept(Server.MySocket,(sockaddr*)&nAddr,&nLength);
AcceptSock.New(defAccept,inet_ntoa(nAddr.sin_addr),Server.ConnectedIPs.size());
Server.ConnectedIPs.push_back(AcceptSock);
newHuman nPlayer;nPlayer.Init(0,0,0,"client",0,"client",0,0,0);
Game.OnlinePlrs.push_back(nPlayer);

if(Server.ReadyToStartGame==0){Server.ReadyToStartGame=1;}
APP.ServerLog.Write(("New Client: "+AcceptSock.Ip).c_str());

}
Server.ThreadKillState=2;
ExitThread(0);
}
DWORD WINAPI HandleNewConnection(void* nID)
{
unsigned int ServerSendData=0,NextThousand=0;
int id=(int)nID;
while(Server.ThreadKillState==0)
{
std::string nMessage="hello from host";
Server.Send(nMessage,-1);
char Recieving[256];
int i=recv(Server.ConnectedIPs[id].mSock,Recieving,256,0);
if(i>0)
{
Recieving='\0';
Server.HandleMessage(Recieving,"Client");
}
else if(i==0)
{
}//quit
else
{
if(Server.LastError("Recv"))
{
Server.DisConnect();
}
}
}
ExitThread(0);
}
DWORD WINAPI ConnectToHost(void* Param)
{
while(Server.ThreadKillState==0)
{
if(Server.Connected)
{
std::stringstream nMessage;
nMessage<<-Game.myX<<','<<Game.myY<<','<<-Game.myZ<<','<<Game.rotX<<','<<Game.rotY<<'\\';
Server.Send(nMessage.str().c_str(),0);

char Recieving[256];
int i=recv(Server.MySocket,Recieving,256,0);

if(i>0)
{
Recieving='\0';
Server.HandleMessage(Recieving,"Client");
}
else if(i==0)
{
MainScreen.LoadScreen("play/online/choose");
APP.ServerLog.Write("Lost Connection");
}
else
{
if(Server.LastError("Recv"))
{
Server.DisConnect();
}
}
}
else if(Server.Connecting)
{
Server.Connect("",0);
}
}
ExitThread(0);
}


Im calling ServerStats::Init() at first, then in the next series of events, this is the order that things get called in (hopefully):

for host:
ServerStats::Disconnect();
ServerStats::Restart();//in to reset stuff
ServerStats::Listen();
ListenForNew();
(after new connection)
a new client is made, where Client_Sock::New() is called, then HandleNewConnection();

for client:
ServerStats::Disconnect()
ServerStats::Restart()//in to reset stuff
ServerStats::Connect()
ConnectToHost()


I just added breakpoints on all the functions... i dont know what could be wrong...
When the client tries to connect to another computer, they get error 10061.
That's connection refused. Typically that means either you have a firewall in the way or the server is not listening on the port you're attempting to connect to.

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.

Well, to be fair i did just test it on 1 other computer ( my friends ) and he had alot of antivirus stuff going on. since it works on a local computer that it *should* work on any other computer? Also, does error 10061 mean that the server is there, but it cant connect because there is a firewall? because i know for sure the host is listening, so it must be the client.
10061, which a quick google or even just running win32 error would tell you, is WSAECONNREFUSED. All that means is that when the machine attempted to connect the remote machine refused the connection (actively in this case).

Testing on your local machine is fine, however it should be noted that firewalls do not monitor the localhost set of IPs (because they're local to the machine), so many such connection issues will not show up until you actually separate the client and server.

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.

Weird... so in this case... it would not be my application? possibly?

EDIT: im going to test on another computer that worked before with a different implementation of code...
Do you have the firewall opened on the port in question, and port forwarding enabled on your router?
Also, I highly recommend reading the articles about NAT pointed at in the networking/multiplayer FAQ.
enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement