WinSock2 questions - really simple READ ME!

Started by
10 comments, last by BeanDog 23 years, 10 months ago
OK, i''ve gone and done it, I''m going through that WinSock2 article. I''ve got a few questions where the article makes assumptions of user knowledge. Remember that I KNOW NOTHING!!! ahem. mainly, I''m interested in information regarding sockets. Now, in the tutorial, it tells you to make this and this and this socket, but doesn''t exactly explain what they do or how they work. For instance, if I do client[NumClients] = accept(s, clientaddr[NumClients], &addr_size); s is a socket on the server, right? Sockets reside on the individual computer, right? So s is a socket on the server, and clientaddr[NumClients] (a sockaddr type) is information regarding the client computer''s ip and such nonsense, correct? And when I do connect(mainsock, target, sizeof(target)); the mainsock is the socket on the client computer, correct? But a port is network-wide, right? So if I bind the server''s socket to, say, port 5001, all the clients would try to connect to 5001, right? So I only have to have one computer bind to a port, that way I don''t try to make 2 duplicate ports. What''s really confusing me is the accept(...) function. When I call it, I pass in a reference to a sockaddr to be filled, and it returns a SOCKET! But wait a sec, this ruins the whole purpose for binding to a port, right? Then the server has a socket to each of the clients and the clients each have exactly ONE socket to the server, correct? This is all fine and dandy, but what exactly does the port do now? Does it ever do anything except provide connections? I''ll come on later and ask more, but I''m tired and confused and I''ll probly go to bed soon anyhoo. Thanks for reading, ~BenDilts( void ); President, BDAA
Advertisement
Yup, I thought of another one already.

When I call the connect or accept functions, do the just go and return immediately, or do they try for a connection for a while before giving up? What I''m asking is, do I have to put the connect and accept into while loops with a timer, or are they smart enough to wait a few seconds?

What are ports for anyway if you just set a SOCKET to listen?! If I have a socket bound to a port, and I call the accept() passing in that socket, does it automatically listen to the port it''s bound to? What if it''s not bound to a port, what happens if I try to accept()?

Help please!

~BenDilts( void );
Try www.flipcode.com

There is a good winsock article there..
Hi,
Sorry I am not a prof either, I am new in WinSock, too.
You can only have one port per server app. Its a kind of appplication identification number. By setting the port you can assure that the Clients find the right server.
I see that you are very confused. Well, I don't know what tutorial you have read, but I recommend that you read the three (or just the 3rd) Network Programming Tutorials from Jered Wierzbicki. He will answer the most of your questions.

Edited by - TheMummy on June 21, 2000 12:36:59 PM
WTF? One port per server application? I think not. You can use all 65k ports if you really want, although you''re going to fight with whatever other applications are using those ports.

Beandog, you sound confused man, and rightfully so. That Winsock 2 tut here is really bad, and has incorrect information. I''m not claiming I''m a god, but I do this shit for a living, so I know what I''m talking about.

When you set up a server, you create a listeng socket, which you bind to your IP and port. After you create and bind the socket, you set it into listening mode with listen (). Now you are ready to accept clients. Accept sits there until it gets something to pass a socket handle from. Remember that a lot of these functions return socket handles (really just an int) and take as a parameter the socket you are connecting through on your local machine. And the sockaddr you pass in on the listen contains information about the socket coming from the client (the remote machine).

As for connect, it tries to connect to a server, but will time out after a while if that connection isn''t there.

I think that''s all your questions. Damn, I may just have to write up some Winsock 2 game programming stuff to put on my site. There are a lot of things that can cause confusion.

-BacksideSnap-
OK Here''s the beginnings of my winsock TCP/IP home-made classes...

class cClient //connection OF A CLIENT TO A SERVER
{
public:
SOCKET sServer; //socket to the server
char ip[15]; //string like "354.63.75.298"
int port; //port to try to connect to server at
cClient(){};
cClient(LPSTR ipServer, int portServer)
{SetStr(ip, ipServer, 15); port = portServer;}
bool StartClient();
void ShutDown();
void SendToServer(char* data, int size);
void ListenToServer(char* data, int size);

};
class cServer
{
public:
SOCKET sListen;//listen for connections here
SOCKET* sClient;//use new during constructor to make array
sockaddr* saClient;//see above, filled in in StartServer()
int port;
int MaxClients;
int NumClients;
cServer(){};
cServer(int portListen, int MaxClients)
{port = portListen, this->MaxClients = MaxClients; sClient = new SOCKET[MaxClients]; saClient = new sockaddr[MaxClients];}
bool StartServer();
void ShutDown();
void SendToClient(int client, char* data, int size);
void SendToClients(char* data, int size);
void ListenToClient(int client, char* data, int size);
};

struct packet //to be send via WinSock2
{
unsigned char type;//basic type - MSG_CREATE, MSG_CHANGE, etc.
unsigned char subtype;
char params[8];//coordinates etc.
};
bool LoadWS2DLL();
void UnloadWS2DLL();
void CreateSocket(SOCKET &s);
void CloseSocket(SOCKET &s);
bool BindSocket(SOCKET &s, int port);
bool ListenForConnectionOnBoundSocket(SOCKET &s, int NumClients);
void SendData(SOCKET s, char* data, int dsize);
void GetData(SOCKET s, char* data, int dsize);


bool LoadWS2DLL()
{
WSADATA w;
int error = WSAStartup (0x0202, &w);
if (error)
return false;
if (w.wVersion != 0x0202)
{
UnloadWS2DLL();
return false;
}
return true;
}
void UnloadWS2DLL()
{
WSACleanup();
}
void CreateSocket(SOCKET &s)
{
s = socket(AF_INET, SOCK_STREAM, 0); //internet-family, streaming, default protocol
}
bool BindSocket(SOCKET &s, int port)
{

sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons (port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);//any IP address
if (bind(s, (LPSOCKADDR)&addr, sizeof(addr)) == SOCKET_ERROR)
return false;
return true;
}
void CloseSocket(SOCKET &s)
{
shutdown(s, SD_BOTH);//can''t send
closesocket(s);
}
bool ListenForConnectionOnBoundSocket(SOCKET &s, int NumClients)
{
if (listen(s, NumClients)==SOCKET_ERROR)
return false;
//listening...
return true;
}

//enough basics, now start the classes

bool cClient::StartClient()
{
if (!LoadWS2DLL())
{
UnloadWS2DLL();
return false;
}
CreateSocket(sServer);

sockaddr_in target;

target.sin_family = AF_INET;
target.sin_port = htons (port);
target.sin_addr.s_addr = inet_addr(ip);//for instance, ip = "25.124.53.62"

if (connect(sServer, (sockaddr*)&target, sizeof(target)) == SOCKET_ERROR)
return false;
return true;
}

bool cServer::StartServer()
{
if (!LoadWS2DLL())
{
UnloadWS2DLL();
return false;
}
CreateSocket(sListen);
if (!BindSocket(sListen, port))
{
UnloadWS2DLL();
return false;
}
if (!ListenForConnectionOnBoundSocket(sListen, MaxClients))
{
UnloadWS2DLL();
return false;
}

//initialized all Server-side sockets, etc., now listen for clients to attach!

NumClients = 0;
//LARGE_INTEGER tsd;//two second delay (actually 5, didn''t want to change var name)
//QueryPerformanceCounter(&tsd);
//QueryPerformanceCounter(&CurrentTicks);
while(NumClients < MaxClients)// && CurrentTicks.QuadPart - tsd.QuadPart > TicksPerSecond.QuadPart*5)//try for new connection if there''s room and time
{
//QueryPerformanceCounter(&CurrentTicks);

CreateSocket(sClient[NumClients]);

int addr_size;//not used really
sClient[NumClients] = accept(sListen, &saClient[NumClients], &addr_size);

if (sClient[NumClients] == INVALID_SOCKET)
break; //can''t accept this one - bad socket! quit trying.
else
NumClients++;
}
return true;
}
void cClient::ShutDown()
{
CloseSocket(sServer);
UnloadWS2DLL();
}
void cServer::ShutDown()
{
for(int i = 0; i < NumClients; i++)
CloseSocket(sClient);
CloseSocket(sListen);
UnloadWS2DLL();
}
void cClient::SendToServer(char* data, int size)
{
SendData(sServer, data, size);
}
void cClient::ListenToServer(char* data, int size)
{
GetData(sServer, data, size);
}
void cServer::SendToClient(int client, char* data, int size)
{
SendData(sClient[client], data, size);
}
void cServer::SendToClients(char* data, int size)
{
for(int i = 0; i < NumClients; i++)
{
SendData(sClient, data, size);<br> }<br>}<br>void cServer::ListenToClient(int client, char* data, int size)<br>{<br> GetData(sClient[client], data, size);<br>}<br>void SendData(SOCKET s, char* data, int dsize)<br>{<br> send(s, data, dsize, 0);<br>}<br>void GetData(SOCKET s, char* data, int dsize)<br>{<br> recv(s, data, dsize, 0);<br>}<br><br>Should be simple enough, many of these functions are just new names for a default function, but it helps me remember. GetData() is much better for me than recv().<br><br>This code crashes when I do this in my program:<br><br>cServer Server;<br>Server.port = 5001;<br>Server.MaxClients = 1;<br>Server.StartServer();<br><br>Thanks for that last post, too. Please help me out, and heck, you can use this code if you want, everybody! Just tell me how you fix it!<br><br>~BenDilts( void );<br> </i>
You''re problem doesn''t really have anything to do with the network code.

sClient[NumClients] = accept(sListen, &saClient[NumClients], &addr_size); 


You haven''t allocated memory for the array. You declare a pointer in the class definition, but you must allocate memory somewhere. If you put something like

sClient = new SOCKET[MAX_CLIENTS] 


somewhere before your server accepts a connection it should work. Be careful with dynamic memory allocation, I see/make this error often.

Let me know if you need more help.


-BacksideSnap-
Oh, you''re right. I put it in my constructor - but I didn''t use that constructor in my code! I''ll check it out, give me a while.
OK, it doesn't crash now--worse.

It doesn't crash.

What I mean is, I call StartServer on port 5001 with 7 maximum clients, with the above code, and it starts up the game nice and dandy. Thing is, nobody connected, but my program thinks they did - unless someone just felt like trying to connect to my IP at port 5001 just at the exact moments I tested the program .

Why does it think this - in my StartServer Code I only add one to the numclients if the socket is valid - but I'm pretty darn sure its invalid! This code resulted in 1 client and exited. Why would that be?

And, when I call the StartClient routine at ip "255.255.255.255", port 5001, I'm also pretty durn sure it should return false. Obviously the connect() returned true, but why?


Edited by - BeanDog on June 24, 2000 5:36:58 PM
Well, maybe you''re using the Asynchronous version of WinSock (I think you do as it was the one used in the wsock2 tutorial here on gamedev). This means the socket functions will return immediately, and their work will be done in the behind. When they''re ready (for example, if a connection was established, or a data packet was sent), your program will receive the windows message you defined before via WM Queue. So you have to check for them to be able to say whether someone has, for example, entered your server. If you''re using synchronous sockets, anyway, i have no idea what the problem is, sorry

hope this helps

pi~

p.s. didn''t have time to go completely through your post though, so please excuse if I''m missing the topic here
Jan PieczkowskiBrainwave Studios

This topic is closed to new replies.

Advertisement