r3dux.org

A number-pimping side project from the valleys in *NEW* upside-down flavour.

  • Home
  • ABOUT
  • OLD SITE
  • SEARCH
  • FEEDBACK

A simple C++/SDL_net chat server & client rewritten

r3dux | November 25, 2011

Back in January this year I was due to be teaching some diploma level programming (roughly equivalent to the UK A/S level for any Brits), and part of that had to deal with network programming with sockets and stuff, so I duly did my research and put together a simple chat server and client in SDL_net. And then my classes changed and I got moved on to teach other stuff. I wasn’t too upset though – I’d learnt a lot, and I’d put up the code to help people out who might be in a similar situation, so it was all good.

But now in November I’m back on programming duty, so I dug up my code, looked it over, and thought Naah – I can’t use that, it’s unweildy, and complex, and it would be a real pain to try to re-use the code. So I’ve gone back to the drawing board and refactored it all into something I hope is a lot more palletable and both easy to use and re-purpose. In effect, I’ve refactored it into two wrappers which now consist of a ServerSocket class and a ClientSocket class.

Check it out…

Cross Platform Socket Server and Clients

Cross platform socket connectivity? That'll be a yes, then...

Socket Server

The old chat server was 250 lines, it’s now down to 77:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// Re-written simple SDL_net socket server example | Nov 2011 | r3dux
// Library dependencies: libSDL, libSDL_net
 
#include <iostream>
#include <string>
#include <SDL/SDL_net.h>
#include "ServerSocket.h"
 
int main(int argc, char *argv[])
{
	// Initialise SDL_net
	if (SDLNet_Init() == -1)
	{
		std::cerr << "Failed to intialise SDL_net: " << SDLNet_GetError() << std::endl;
		exit(-1);
	}
 
	// Create a pointer to a ServerSocket object
	ServerSocket *ss;
 
	try
	{
		// Try to instantiate the server socket
		// Parameters: port number, buffer size (i.e. max message size), max sockets
		ss = new ServerSocket(1234, 512, 3);
	}
	catch (SocketException e)
	{
		std::cerr << "Something went wrong creating a SocketServer object." << std::endl;
		std::cerr << "Error is: " << e.what()   << std::endl;
		std::cerr << "Terminating application." << std::endl;
		exit(-1);
	}
 
	try
	{
		// Specify which client is active, -1 means "no client is active"
		int activeClient = -1;
 
		// Main loop...
		do
		{
			// Check for any incoming connections to the server socket
			ss->checkForConnections();
 
			// At least once, but as many times as necessary to process all active clients...
			do
			{
				// ...get the client number of any clients with unprocessed activity (returns -1 if none)
				activeClient = ss->checkForActivity();
 
				// If there's a client with unprocessed activity...
				if (activeClient != -1)
				{
					// ...then process that client!
					ss->dealWithActivity(activeClient);
				}
 
			// When there are no more clients with activity to process, continue...
			} while (activeClient != -1);
 
		// ...until we've been asked to shut down.
		} while (ss->getShutdownStatus() == false);
 
	}
	catch (SocketException e)
	{
		cerr << "Caught an exception in the main loop..." << endl;
		cerr << e.what() << endl;
		cerr << "Terminating application." << endl;
	}
 
	// Shutdown SDLNet - our ServerSocket will clean up after itself on destruction
	SDLNet_Quit();
 
	return 0;
}

Socket Client

And the old chat client was 313 lines, which is now down to 83:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
// Re-written simple SDL_net socket client example | Nov 2011 | r3dux
// Library dependencies: libSDL, libSDL_net
 
#include <iostream>
#include <string>
#include <SDL/SDL_net.h>
 
#include "ClientSocket.h"
 
int main(int argc, char *argv[])
{
	// Initialise SDL_net (Note: We don't initialise or use normal SDL at all - only the SDL_net library!)
	if (SDLNet_Init() == -1)
	{
		std::cerr << "Failed to intialise SDL_net: " << SDLNet_GetError() << std::endl;
		exit(-1);
	}
 
	// Create a pointer to a ServerSocket object
	ClientSocket *cs;
 
	try
	{
		// Try to instantiate the client socket
		// Parameters: server address, port number, buffer size (i.e. max message size)
		// Note: You can provide the serverURL as a dot-quad ("1.2.3.4") or a hostname ("server.foo.com")
		cs = new ClientSocket("127.0.0.1", 1234, 512);
	}
	catch (SocketException e)
	{
		std::cerr << "Something went wrong creating a ClientSocket object." << std::endl;
		std::cerr << "Error is: " << e.what()   << std::endl;
		std::cerr << "Terminating application." << std::endl;
		exit(-1);
	}
 
	try
	{
		// Attempt to connect to the server at the provided address and port
		cs->connectToServer();
 
		string receivedMessage = "";
 
		cout << "Use /quit to disconnect or /shutdown to shutdown the server." << endl;
 
		// Display the initial prompt
		cs->displayPrompt();
 
		// Run the main loop...
		do
		{
			// Check if we've received a message
			receivedMessage = cs->checkForIncomingMessages();
 
			// If so then...
			if (receivedMessage != "")
			{
				// Display the message and then blank it...
				cs->displayMessage(receivedMessage);
 
				// ...and then re-display the prompt along with any typed-but-not-yet-sent input
				cs->displayPrompt();
			}
 
			// Get and deal with input from the user in a non-blocking manner
			cs->getUserInput();
 
		// ... until we decide to quit or the server is shut down
		} while ( (cs->getShutdownStatus() == false));
 
	}
	catch (SocketException e)
	{
		cerr << "Caught an exception in the main loop..." << endl;
		cerr << e.what() << endl;
		cerr << "Terminating application." << endl;
	}
 
	// Shutdown SDLNet - our ClientSocket will clean up after itself on destruction
	SDLNet_Quit();
 
	return 0;
}

On top of all this we have try/catch exception handling, a nice encapsulated & easy to work-with/modify/extend design and debug flags to control whether the client/server should be verbose or run silently. Obviously the chat client itself can’t run completely silently – you wouldn’t be able to read the messages being sent back and forth! – but when debug is off it only ever outputs anything when it receives a message or when the user enters messages to send, so it’s pretty darn quiet.

Oh, and it now comes in Linux and Windows flavours =D

Overall I’m really happy with it – it’s taken a few days to properly redesign and test (not to mention the issues involved with porting to Windows) – but I think the next time I need to do some socket stuff with C++ I’d be able to grab this code, make whatever modifications I need and get something up and running in no time.

Awthome! =P

Download links

  • Linux Client and Server Code (Code::Blocks projects, libs not included)
  • Windows Client and Server Code (Visual Studio 2008 projects, libs included)

Notes on Building for Windows

The windows client and server projects have some important tweaks made for them to compile, and it’s worth mentioning what they are:

  • The solution (which contains two projects) comes comes with a copy of the SDL and SDL_net libs and headers all merged together in the SDL folder (well, there are separate libs and include folders, but all the headers from both are in the include folder and all the libs from both are in the libs folder).
  • Each project has the following libraries linked in: SDL.lib, SDLmain.lib and SDL_net.lib, these libraries point to…
  • SDL.dll and SDL_net.dll which are in the solution’s Debug folder, so you can compile and build from Visual Studio, BUT you’lll need to copy these two dll files into the same folder as the SocketServer-Rewritten.exe or SocketClient-Rewritten.exe folders to run the executables “standalone” in other locations as opposed to build-and-run-from-visual-studio style!
  • The projects are defined as console applications, and because SDLmain.lib defines the main function as int main(int argc, char *argv[]) and not just int main() you MUST keep the definition of main in-line with the SDLmain.lib definition.
  • Finally, the projects will only build successfully in debug mode. Why? I’ve no idea. If you know how to fix it then go for it!

Comments
7 Comments »
Categories
Coding
Tags
C++, Client, networking, SDL_net, Server, Socket
Comments rss Comments rss
Trackback Trackback

San Cisco – Awkward

r3dux | November 22, 2011

This track was on Triple J as I was driving in to work this morning – a catchy song about stalking, who woulda thunk it? ;)

YouTube Preview Image

Free download available at: triplejunearthed.com/SanCisco.

Comments
No Comments »
Categories
Music
Tags
Awkward, San Cisco, Stalking
Comments rss Comments rss
Trackback Trackback

Sebastian Thrun is Awesome

r3dux | November 19, 2011

I’m doing the Stanford online AI class this year, taught by Professor’s Sebastian Thrun and Peter Norvig. And up in week 5, unit 11 is Markov Decision Processes (MDPs), Hidden Markov Models (HMMs) and State Transition Probabilities. Sounds dry, right?

Check this out…

YouTube Preview Image

Oh. My. God.

As a teacher myself, and one who genuinely tries hard to interest and engage students, Sebastian is a role-model. How absolutlely RARING-TO-GO is he?! To paraphrase: “I CAN’T WAIT to teach you all about this, and that, and this other cool shit! And you can use it for all kinds of neat stuff! Woo-hoo!” =DDD

And yeah, the course isn’t easy, and it requires time and effort and commitment – but it’s fun! And it’s rewarding, and I’m inspired as a student, and blown-away as a teacher.

If more teachers had this kind of passion, I sincerely believe that the world would be an entirely different place.

Comments
No Comments »
Categories
Life
Tags
AI, AIClass, Class, Optimism, Sebastian Thrun, Teaching
Comments rss Comments rss
Trackback Trackback

How-To: Fix Gnome 3 sessions failing to start

r3dux | November 18, 2011

I recently changed my LMDE repos and did a full update/upgrade/dist-upgrade – which landed me with Gnome 3… only it didn’t work, and only fallback mode was available.

Unfortunately, fallback mode isn’t very good.

When attempting to start a Gnome 3 session proper, I was getting an error message like this:

Oh no! Something has gone wrong.
A problem has occurred and the system can’t recover.
Please log out and try again.
[Log out]

Then you had to click the [Log Out] button and start a fallback mode session if you wanted to actually be able to do anything with the machine.

So, I did a bit of googling and the easiest way to fix it that I’ve found is to go to the folder: ~/.config/autostart/, create file called Gnome-Shell.desktop (the name doesn’t really matter as long as it ends with .desktop) and the put the following contents in it:

[Desktop Entry]
Type=Application
Exec=gnome-shell --replace
Hidden=false
NoDisplay=false
X-GNOME-Autostart-enabled=true
Name[en_US]=Gnome Shell
Name=Gnome Shell
Comment[en_US]=
Comment=

BUT – for all this to work properly I had to do a little house cleaning first as I already had a “Gnome-Session.desktop” autostart item which was trying to start Gnome 2 (which isn’t even on the system anymore) and was causing mischief with the Gnome 3 session, so the safest way to do this is probably to:

  1. Create a copy of the entire ~/.config/autostart folder,
  2. Now you’ve got a copy in case things go wrong, go into the autostart folder and strip out anything you think might interfere (such as any existing Gnome-Session stuff),
  3. Add the new Gnome-Shell.desktop file with contents as above, and finally
  4. Log out then back in to a proper Gnome 3 session and you should be good to go!
Gnome 3

Gnome 3 window management is a bit different to the norm, but I'm finding it actually keeps things quite uncluttered...

I’ve got to say that apart from a few niggles (like the entire Ctrl+Delete to delete a file, Shift+Ctrl+Delete to permanently delete a file rubbish) I’m actually quite liking Gnome 3 so far – it’s a bit like Unity, but without crashing five times a day…

Not a bad start =D

Comments
1 Comment »
Categories
How-To, Linux
Tags
autostart, Desktop, Fallback, Gnome, Gnome 3, Oh no!, Session
Comments rss Comments rss
Trackback Trackback

How-To: Remove a (known) password from a PDF file in Linux

r3dux | November 17, 2011

I had a PDF the other day which required me to enter a password before viewing it, which is something I’d never seen before, so being a chancer I just slapped enter and it worked (i.e. there was no password, or more accurately the password was blank). However, keeping a file in that state is just stupid, so I wanted the “password” removed – and it turns out that it’s dead simple to do in Linux.

Two Stepper

  1. Install qpdf with synaptic or the command:

    sudo apt-get install qpdf
  2. Issue the following command:
    qpdf --password=YOURPASSWORD-HERE --decrypt INPUT-FILE.pdf OUTPUT-FILE.pdf

    So, if your password protected pdf is called foo.pdf and the password is empty (i.e. “”) like in my case, you just issue something like this:

    qpdf --password= --decrypt foo.pdf foo-no-password.pdf

Job done!

Comments
No Comments »
Categories
Linux
Tags
Decode, Decrypt, Password, PDF, qpdf, Removal, Remove, Strip
Comments rss Comments rss
Trackback Trackback

« Previous Entries

Translate

Categories

Archives

Tags

3D ActionScript ActionScript 3.0 Adobe AI Ballarat Bash C++ Class Convert CS4 Effect Error Film Flash GLSL Gnome Hack How-To install Jaunty Java Kinect Linkage Linux Mash-Up Microsoft Motion OpenGL Particle Problem PS3 Remix Retro script Slides Sound Systems Texture Ubuntu Video VirtualBox Wii Windows XBox

Gamercard

OpenR3dux

Misc.

Flattr this

RSS Feed

r3dux twitter feed



“My shoulder is laden with parrots.”

 - Shetboy

rss Comments rss valid xhtml 1.1 design by jide powered by Wordpress get firefox