Winsock and UDP (client/server app)

Started by
18 comments, last by hplus0603 13 years, 6 months ago
right now, it's the same machine (=, coming up.
Advertisement
Here is some more:

enum{	PortTCP = 2048,	PortUDP = 2050,};boolServer::Initialize(){#ifdef _DEBUG	Debug* debug = (Debug*)Engine::GetModule(ModuleDebug);	debug->AddFadingText("initializing server");#endif	time = (Time*)Engine::GetModule(ModuleTime);	if (! InitializeTCPSocket())	{		return false;	}	if (! InitializeUDPSocket())	{		return false;	}	InitializeThreads();#ifdef _DEBUG	Debug* debug2 = (Debug*)Engine::GetModule(ModuleDebug);	debug2->AddFadingText("success");#endif	return true;}boolServer::InitializeTCPSocket(){	if (! tcpSocket.Initialize(IPPROTO_TCP))	{		LOGERROR(Network::GetLastError().c_str());		return false;	}	if (! tcpSocket.Bind(PortTCP))	{		LOGERROR(Network::GetLastError().c_str());		return false;	}	if (! tcpSocket.Listen())	{		LOGERROR(Network::GetLastError().c_str());		return false;	}	return true;}boolServer::InitializeUDPSocket(){	if (! udpSocket.Initialize(IPPROTO_UDP))	{		LOGERROR(Network::GetLastError().c_str());		return false;	}	if (! udpSocket.Bind(PortUDP))	{		LOGERROR(Network::GetLastError().c_str());		return false;	}	return true;}bool Socket::Bind(int port) const{	sockaddr_in socketAddress;	GetSocketAddress(socketAddress, INADDR_ANY, port);	int result = bind(		descriptor,		(SOCKADDR*)&socketAddress,		sizeof(socketAddress));	if (result != 0)	{		LOGERROR(Network::GetLastError().c_str());		return false;	}	return true;}
Ok so you should perform steps in that order:

1. Create server socket
2. Bind server socket to known port
3. Create client socket
4. Send data to server ip/port
5. Wait for data on server using recvfrom (which gives you client's ip/port)
6. Send data to client descriptor (5)
7. Receive data from server through client socket

That should work if your firewall isn't interfering.
Quote:Original post by Madhed
Ok so you should perform steps in that order:

1. Create server socket
2. Bind server socket to known port
3. Create client socket
4. Send data to server ip/port
5. Wait for data on server using recvfrom (which gives you client's ip/port)
6. Send data to client descriptor (5)
7. Receive data from server through client socket

That should work if your firewall isn't interfering.


Ok great! thanks for your help, I'm gonna try this tomorrow, it should really work. I Really need to sleep now, cheers! (=. Will make a post tomorrow how it worked.
Alright,
here is some code from me which, I just checked, works.

//bind server to port 12345Socket server(12345);//create unbound client socketSocket client; //send data to serverclient.send(0x7f000001/*127.0.0.1*/, 12345, "Hello", 5);//Wait some time    Sleep(100);//prepare buffer to receive datachar buffer[6] = {0};unsigned long clientIp = 0;unsigned short clientPort = 0;//receive message and store client ip/portif (server.receive(buffer, 6, &clientIp, &clientPort)) {  std::wstringstream str;  str << buffer;  MessageBox(0, str.str().c_str(), L"Message Arrived", MB_OK);  //send message back  server.send(clientIp, clientPort, "AHOI", 4);  //Wait  Sleep(100);  char clientBuffer[5] = {0};  if (client.receive(clientBuffer, 5)) {    std::wstringstream str;    str << clientBuffer;    MessageBox(0, str.str().c_str(), L"Message Arrived", MB_OK);  }}


:)

[Edited by - Madhed on September 27, 2010 5:50:35 PM]
Thanks Madhed for the cool tutorial. teaching everyone here. :)
Ah, well that looks great. Though I'm not a fan of initalizing stuff in the ctor. Well I'm at work now, gonna try it out later today. thanks for the code.
Hell yeah! I'm sending udp packets between client/server now. Finally I can continue with some gameplay code... Thanks all for help!
Quote:Original post by Mufflot
Hell yeah! I'm sending udp packets between client/server now. Finally I can continue with some gameplay code... Thanks all for help!


Great. Now you can start doing the nasty stuff ;)

Create an (optional) reliable layer above pure UDP that resends packets if they get dropped, returns packets in correct order, optimize packet size, etc.

Quote:Original post by Mufflot
Ah, well that looks great. Though I'm not a fan of initalizing stuff in the ctor.


RAII my friend. Google it up! Though, in the case of my Socket class, I treat unbound sockets to be completely initialized. The binding ctor is just syntactic sugar.
The main problem with RAII is the fact that the destructor isn't called if the constructor throws. So each sub-resource you need also needs to be RAII (because destructors for contained and base objects are called). It's kind-of like const-correctness; you have to push it all the way out to the leaves of your code.

Regarding a higher-level "reliable" packet protocol, you really need to separate "messages" from "packets." "Messages" delivery types typically include reliable-in-order, never-reordered-but-possibly-dropped and never-dropped-but-possibly-reordered. For messages, "possibly duplicated or reordered" doesn't make much sense, either from implementation nor user point of views.

Many messages go into each single packet. The packet has sequence numbers and acknowledgement to support the different reliability modes. It probably also has timing information to support clock sync and latency calculation. The messages themselves don't need sequence numbers; you can build all that on top of the data from the packets. You may optionally want to support per-message addressing ("send this to object 3"), and/or multiple channels where the reliability guarantees (in-order, etc) are enforced per channel rather than globally across the connection.

This ends up being a much more efficient structure to use than a naive "message == packet" system.
enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement