Overview
Examples
Screenshots
Comparisons
Applications
Download
Documentation
Tutorials
Bazaar
Status & Roadmap
FAQ
Authors & License
Forums
Funding Ultimate++
Search on this site
Search in forums












SourceForge.net Logo
Home » Community » Newbie corner » Adding a socket to a GUI application
Adding a socket to a GUI application [message #48129] Mon, 22 May 2017 10:15 Go to next message
Giorgio is currently offline  Giorgio
Messages: 175
Registered: August 2015
Experienced Member
Hi there,
I have my application with its GUI that connects to a db and makes stuff. It goes ok. Now I need the ability for the application to listen to a port and, when it receives a specific command, the application needs to modify its behaviour.

My main.cpp is like this

#include <CtrlLib/CtrlLib.h>
#include <Sql/sch_schema.h>
#include <Sql/sch_source.h>
//Other includes

using namespace Upp;

GUI_APP_MAIN
{
	String User, Pass, Schema, IP;
	int port;
	
	User = "fooo";
	Pass = "bar";
	Schema = "test";
	IP = "192.168.1.2";
	port = 3306;

	//Connection to the DB
		MySqlSession session;
		if(err_conn = session.Connect(User, Pass, Schema, IP, port)) {
			SQL = session;
			SqlSchema sch(MY_SQL);
			All_Tables(sch);
		}
		else {
			SetExitCode(1);
		}

	//Main window of the GUI
	HomeScreen hs;
	hs.Run();
	
}


I have no experience in sockets, but my guts tell me that I have to fork somewhere before the .Run() command.
Any suggestion (including links to relevant documentation and RTFM) is appreciated.
Regards,
Gio

Re: Adding a socket to a GUI application [message #48134 is a reply to message #48129] Tue, 23 May 2017 07:06 Go to previous messageGo to next message
nlneilson is currently offline  nlneilson
Messages: 644
Registered: January 2010
Location: U.S. California. Mojave &...
Contributor
Hi
read the threads in the forum:
U++ MT-multithreading and servers.
and try a search in the upp forums for sockets.
Also do a google search on the internet for sockets.
Whether you have a gui app or not the operation of sockets is basically the same.
I use a socket to communicate from a upp c++ app with a Java app. If you stay within C++ it is a bit easier but the concept is the same. I think there is an example that comes with upp for the socket server and a client.

It will be interesting to see what you come up with for your db.

Neil
edit:
"I have to fork somewhere before the .Run() "
You may need to run the server code in a separate thread.

[Updated on: Tue, 23 May 2017 07:46]

Report message to a moderator

Re: Adding a socket to a GUI application [message #50333 is a reply to message #48134] Wed, 26 September 2018 18:51 Go to previous messageGo to next message
Giorgio is currently offline  Giorgio
Messages: 175
Registered: August 2015
Experienced Member
Hi there,
I put this question aside for a while, few days ago I resumed it.

I had a look to threads and tcpsocket as suggested. For a starter I decided to focus on thread. So, I forked before the .Run() and put in the thread the code to manage the socket. I ended up with this:

void tagidSocket()
{
	//Socket
	RLOG("Socket's thread started");
	for(;;) {
		if(Thread::IsShutdownThreads())
			return;
		RLOG("I'm still alive");
		Sleep(1000);
	}
}

GUI_APP_MAIN{
	//Reading a .ini file, connection to a db
	[...]

	Thread t;
	t.Run(callback(tagidSocket));
	app.Run();
    
	RLOG("Exiting, terminating socket");
	Thread::ShutdownThreads();
}


This works as expected: I can use my application normally, I can see in the log the sentence "I'm still alive" several times, and when I close the applications it exits nicely / does not hung up.

After that I put the socket management in the equation and here came the problems. I began using the very same code used in the example "SocketServer". I copied everything in my tagidSocket() function. This is the result (GUI_APP_MAIN does not change):

void tagidSocket()
{
	TcpSocket server;
	if(!server.Listen(23456, 5)) {
		RLOG("Unable to initialize server socket");
		return;
	}
	RLOG("Socket started, waiting for requests...");
	for(;;) {
		if(Thread::IsShutdownThreads())
			return;
		TcpSocket s;
		if(s.Accept(server)) {
			String w = s.GetLine();
			//Cout() << "Request: " << w << " from: " << s.GetPeerAddr() << '\n';
			RLOG("Request: " + w + " from: " + s.GetPeerAddr() + '\n');
			if(w == "time")
				s.Put(AsString(GetSysTime()));
			else
				s.Put(AsString(3 * atoi(~w)));
			s.Put("\n");
			
		}
	}
}


With this change, when I launch my application everything is ok, I can connect to the socket and exchange data, but when I close my application it hangs and I have to kill it manually.

I try to debug the problem and I found out that the code responsible for the problem is the following: if(s.Accept(server)) { [...] }.

If I comment out everything in the if above (and also the if itself), the application can be closed normally (but of course a socket without the "listening" part makes no sense).

Why is this happening?

Regards,
gio

[Updated on: Wed, 26 September 2018 18:53]

Report message to a moderator

Re: Adding a socket to a GUI application [message #50334 is a reply to message #50333] Wed, 26 September 2018 22:03 Go to previous messageGo to next message
Oblivion is currently offline  Oblivion
Messages: 574
Registered: August 2007
Location: Turkey
Contributor
Hello Giorgio,

I'm afraid (as it'll make things somewhat complicated) what you seem to need is a socket in non-blocking mode.
Yet, there might be a simple solution for the test code you've provided:

void tagidSocket()
{
	TcpSocket server;
	if(!server.Listen(23456, 5)) {
		RLOG("Unable to initialize server socket");
		return;
	}
	RLOG("Socket started, waiting for requests...");
	try {
		while(!Thread::IsShutdownThreads()) {
			TcpSocket s;
			s.WhenWait = [=]
			{
				if(Thread::IsShutdownThreads())
					throw Exc("Thread is shut down.");
			};
			if(s.Accept(server)) {
				String w = s.GetLine();
				RLOG("Request: " + w + " from: " + s.GetPeerAddr() + '\n');
				if(w == "time")
					s.Put(AsString(GetSysTime()));
				else
					s.Put(AsString(3 * atoi(~w)));
				s.Put("\n");
				
			}
		}
	}
	catch(const Exc& e) {
		RLOG(e);
	}
}


Now, the above code should work. But I can't guarantee it will continue to work in a complex code. That's why you need to get yourself familiar with non-blocking operations.

Best regards,
Oblivion


[Updated on: Wed, 26 September 2018 22:47]

Report message to a moderator

Re: Adding a socket to a GUI application [message #50337 is a reply to message #50334] Thu, 27 September 2018 09:23 Go to previous message
Giorgio is currently offline  Giorgio
Messages: 175
Registered: August 2015
Experienced Member
Hi Oblivion,
thank you for your support, I will read some documentation on blocking and non-blocking operations.
Regards,
gio
Previous Topic: print the Http Request before sending it
Next Topic: I don't understand Moveable
Goto Forum:
  


Current Time: Sun Aug 18 06:35:13 CEST 2019

Total time taken to generate the page: 0.01311 seconds