C++ Winsock Connecting to an IP Address Problem
#1 Members - Reputation: 432
Posted 21 February 2012 - 06:52 PM
#4 Members - Reputation: 432
Posted 21 February 2012 - 07:40 PM
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[i]='\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[i]='\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...
#6 Senior Moderators - Reputation: 3113
Posted 21 February 2012 - 08:12 PM
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.
ScapeCode - Blog | SlimDX
#7 Members - Reputation: 432
Posted 21 February 2012 - 08:19 PM
#8 Senior Moderators - Reputation: 3113
Posted 21 February 2012 - 08:25 PM
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.
ScapeCode - Blog | SlimDX
#10 Moderators - Reputation: 3286
Posted 21 February 2012 - 10:19 PM
Also, I highly recommend reading the articles about NAT pointed at in the networking/multiplayer FAQ.
#11 Moderators - Reputation: 5028
Posted 22 February 2012 - 09:44 AM
Some ideas to diagnose connectivity issues:
- If you have a spare machine, try get it working on a local area network first, before trying it on the internet. This can remove external router configuration as a source of error.
- Your router might have a firewall too. I have had a home router where the firewall would block incoming connections, even when port forwarding was configured.
- Try turning off the local firewall on each of the machines (probably start with the server) in turn.
- Eliminate your code as a source of error by using existing, well tested client/server programs rather than your own one
- The built-in telnet tool on Windows can be useful for TCP connections
- If you were using UDP, I'm not aware of any default tools but you can download UDP based programs to fill this gap
- The ping tool can also help diagnose connectivity issues.
#12 Members - Reputation: 432
Posted 22 February 2012 - 05:42 PM
I went to look at the example code, and where i bind the port, it is supposed to be "0.0.0.0", but i have a loopback address. /^3^\
the only problem now is that when the client joins, their application crashes. but thats for me to fix now!
Thanks for the help!
#13 Members - Reputation: 103
Posted 29 February 2012 - 10:16 AM






