get next open tcp port in windows - c++

How is it possible to get next open tcp port on windows
I've searched the web and i came across TcpPortsGatherer written in Qt...
the only problem is that its not available in my current Qt version or it should be used as a plugin
so I'm looking for a way to use TcpPortsGatherer Class
or just use native windows libraries if any is available
Update :
I've Used Sebastian's approach like below to bind the found port to an external binary that I run but it always assign the port 1025 to the executable , how can i fix this ?
QTcpSocket *socket = new QTcpSocket();
qint16 port = 1025;
while(!socket->bind(port, QAbstractSocket::DontShareAddress))
port++;
socket->close();
socket->deleteLater();

Just specify port zero and bind. The system will give you the next available port. No loop required.

You could just try using QTcpSocket::bind(). It will return a bool(true) if port open was successfull.
QTcpSocket *socket = new QTcpSocket();
qint16 port = 1025;
while(!socket->bind(port, QAbstractSocket::DontShareAddress))
{
port++;
}
socket is now bound to port.

Related

Qt - QUdpSocket bind failed constantly

I have these 2 lines of code.
I need a socket that just receives data
The first method is working, and I receive date (from the ip/port in the second method)
The second method is always returning false.
I don't understand the difference and can't find the problem.
Any one have any idea how to resolve this or what I'm doing wrong?
udpSocket = new QUdpSocket();
bool result = udpSocket->bind(QHostAddress::Any, 7755);
QHostAddress address("the ip")
udpSocket = new QUdpSocket();
bool result = udpSocket->bind(address , 7755);
In first method, when you bind the socket bind(QHostAddress::Any, 7755) it will listen on all interfaces on your system; thus it will bind successfully knowing that at least one interface is up.
In the second method, when you set the IP Address with QHostAddress address("the ip") you need to make sure that an interface is up with that IP address at your system (use ipconfig on Win / ifconfig on Linux).
Now the constructor will automatically detect from the string passed ("ip address") whether its IPv4 or IPv6.
If you are not specifying a type, then you can construct the address as Any and bind your socket to it:
QString string("192.168.1.1");
QHostAddress address(QHostAddress::Any);
address.setAddress(string);
udpSocket = new QUdpSocket();
bool result = udpSocket->bind(address , 7755);

Unable to open UDP socket

I'm trying to create a UDP socket with boost to send and receive data. Here's the relevant code:
// Create IO service
mIoService = std::make_unique<boost::asio::io_service>();
// Create local endpoint on random port
mLocalEndpoint = std::make_unique<udp::endpoint>(udp::v4(), 0);
// Create socket
mSocket = std::make_unique<udp::socket>(*mIoService, *mLocalEndpoint);
mSocket->open(mLocalEndpoint->protocol());
This gives me the following exception:
open: Already open
I have fiddled around with this code for quite some time now, but the result stays the same. What am I missing here?
It looks like you try to create a UDP end point on port 0. I'd assume that it may be already used, so you can try to change a port:
mLocalEndpoint = std::make_unique<udp::endpoint>(udp::v4(), 40000);

CSocket does not work on LAN

I'm learning network-programming and try to develop a simple socket application that used CSocket class from MFC. And found myself hitting a wall that need some help.
I want the server side listens on a certain port, example 1001. Then from other computer, on the same sub-net, it should successfully telnet to that port. My program works correctly on localhost, but fail on the LAN, although I have opened that port on firewall of listener.
Here is my code from listener:
//CListenSocket is derived from CSocket
CListenSocket myListener;
myListener.Create(1001);
myListener.Listen();
//OnAccept()
//CConnectSocket is also derived from CSocket
CConnectSocket myConnect;
myListener.Accept(myConnect);
I built the release version using VS2008, here is the screenshot of the configuration properties:
So at this stage, when I run the program, netstat -an show this line:
TCP 0.0.0.0:1001 0.0.0.0:0 LISTENING
Then on that machine telnet 127.0.0.1 1001, this line appears.
TCP 127.0.0.1:1001 127.0.0.1:2681 ESTABLISHED
So I think my code is correct. After that I tried from other machine with the same sub-net, and the telnet fail:
Connecting To 192.168.2.199...Could not open connection to the host, on port 1001: Connect failed
Note: that my listener is on 192.168.2.199, and the connector is on 192.168.2.3. Both nodes can successfully ping and sharing file with each other. I also add both Inbound Rule and Outbound Rule for the program on my firewall, here is the properties of the rule:
For more information: On my listener node, there is Apache HTTP server installed on it, so I have the other node telnet to port 80, and it works...
So where did I miss? please help, thank you in advance.
EDITION 1:
Attempt for troubleshooting
So after hitting my head to the table for a while, I quickly make a decision for not use telnet for client anymore. But make a small client program to catch errors:
//CClientSocket is derived from CSocket
CClientSocket clientSocket;
clientSocket.Create();
int iConnect = clientSocket.Connect(ipAddress,1001) //ipAddress is a variable of MFC's text box on GUI.
switch (iConnect)
{
case 0:
{
DWORD errorNumber = ::GetLastError(); //catch error code
CString s_errorNumber;
s_errorNumber.Format("%d",errorNumber); //format to CString for easy echo
MessageBox("Connection fail :"+s_errorNumber)
clientSocket.ShutDown(CAsyncSocket::both);
clientSocket.Close();
break;
case SOCKET_ERROR:
if (::GetLastError() != WSAEWOULDBLOCK)
clientSocket.ShutDown(CAsyncSocket::both);
else
clientSocket.AsyncSelect();
break;
default:
{
MessageBox("Connection Established.");
}
break;
}
And the error number is: 10061. I checked this code on MSDN an it is WSAECONNREFUSED-Connection refused.
Now we know the problem here must be somewhere in the listener's firewall... still hiting my head to the table.

C++ socket option reuse port

I have a problem with a c++ socket.
I'm using CAsyncSocket from MFC that i want to join a multicast group.
Also I need to have multiple listener on this group and here is where i get in trouble.
I found some examples on the web but it doesn't seems to work.
Here is my code:
//create socket on port 17233
BOOL bRet = Create(17233,SOCK_DGRAM, FD_READ);
//set reuse socket option
BOOL bMultipleApps = TRUE;
bRet = SetSockOpt(SO_REUSEADDR, (void*)&bMultipleApps, sizeof(BOOL), SOL_SOCKET);
//join multicast group
ip_mreq m_mrMReq; // Contains IP and interface of the host group
m_mrMReq.imr_multiaddr.s_addr = inet_addr((LPCSTR)"224.30.0.1"); /* group addr */
m_mrMReq.imr_interface.s_addr = htons(INADDR_ANY); /* use default */
int uRes =setsockopt(m_hSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char FAR *)&m_mrMReq, sizeof(m_mrMReq));
There are no errors when i run this.
But when i try to run another instance of the app it fails to create a new socket on that port because the port is in use.
I have done this in C# and it worked fine like this:
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, port);
s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
s.Bind(ipep);
IPAddress ip = IPAddress.Parse(mcastGroup);
s.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(ip, IPAddress.Any));
s.SetSocketOption(SocketOptionLevel.IP,SocketOptionName.MulticastTimeToLive, int.Parse("1"));
So if any body sees a problem with my code or have some tips i will gladly appreciated.
EDIT 1:
Is CAsyncSocket a TCP socket?
EDIT 2:
After reading Can two applications listen to the same port?
I think i made a confusion. I need a Multicast UDP port that can be access by multiple application using SO_REUSEADDR
Edit for Clarification:
BOOL bRet = Create(17233,SOCK_DGRAM, FD_READ)
Creates an UDP socket and bind's to to port 17223.
For SetSockOpt(SO_REUSEADDR, (void*)&bMultipleApps, sizeof(BOOL), SOL_SOCKET); to work you need to set it before binding as #Hasturkun said.
The final working code looks like this:
BOOL bRet = Socket(SOCK_DGRAM, FD_READ);
if(bRet != TRUE)
{
UINT uErr = GetLastError();
std::cout<<"Error:"<<uErr<<std::endl;
return FALSE;
}else{
std::cout<<"Create sock: OK"<<std::endl;
}
//add reuse
BOOL bMultipleApps = TRUE; /* allow reuse of local port if needed */
SetSockOpt(SO_REUSEADDR, (void*)&bMultipleApps, sizeof(BOOL), SOL_SOCKET);
//bind
bRet = Bind(17233, NULL);
if(bRet != TRUE)
{
UINT uErr = GetLastError();
std::cout<<"Error(BIND):"<<uErr<<std::endl;
}else{
std::cout<<"BIND sock: OK"<<std::endl;
}
Thanks,
Gabriel
;
You should be able to separate the creation of the socket from the binding, create the socket using Socket, eg.
BOOL bRet = Socket(SOCK_DGRAM, FD_READ);
Then bind it with Bind after setting the sockopt
BOOL bMultipleApps = TRUE;
bRet = SetSockOpt(SO_REUSEADDR, (void*)&bMultipleApps, sizeof(BOOL), SOL_SOCKET);
bRet = Bind(17233, NULL);
This happens, i guess, because you are binding a client socket to a specific port and address. Maybe on its constructor:
BOOL bRet = Create(17233,SOCK_DGRAM, FD_READ);
You should not binding a client socket to an address. Let windows manage this for you. You should have a option to not create the socket passing a specific port, or if you do not, you should create the socket using another port.
Also, the BOOL bMultipleApps = TRUE; option does not work the way you think it does. It sets a linger option in the socket, but once created and listening, the socket (i mean the socket port) cannot be used in other applications no mather what you do.
Check this out: so-linger-and-closing-socketswinsock
EDIT:
I also dont know that the value of port in your c# code:
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, port);
Are you sure that port does not get a different value every time you run the app?
As I said, try to create the socket in a different port to see what happens. Google for so_linger to know what it means.
EDIT 2:
Take a look at: Can two application listen to the same port?
EDIT 3:
Maybe your c# code:
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, port);
is binding the address to a different NIC. Do you have 2 nics at the same computer? If you do, you can bind the same port in both of them.
EDIT 4:
Example of using UDP sockets: Sending & Receiving UDP Datagrams with MFC's CAsyncSocket
If boost is an option for you, consider using Asio for this. It is very straight-forward and this example shows a simple multicast receiver.
The important part for multiple listeners is:
socket_.set_option(boost::asio::ip::udp::socket::reuse_address(true));
If you're unclear what your application is doing, just run netstat and you'll see e.g. the sockets and how they are bound (IP, port and protocol):
netstat -an
...and look for the port you're interested in. If you run multiple applications listening to the same port you should see multiple entries for the same port with UDP as protocol.

QextSerialPort connection problem to Arduino

I'm trying to make a serial connection to an Arduino Diecimila board with QextSerialPort. My application hangs though everytime I call port->open(). The reason I think this is happening is because the Arduino board resets itself everytime a serial connection to it is made. There's a way of not making the board reset described here, but I can't figure out how to get QextSerialPort to do that. I can only set the DTR to false after the port has been opened that's not much help since the board has already reset itself by that time.
The code for the connection looks like this:
port = new QextSerialPort("/dev/tty.usbserial-A4001uwj");
port->open(QIODevice::ReadWrite);
port->setBaudRate(BAUD9600);
port->setFlowControl(FLOW_OFF);
port->setParity(PAR_NONE);
port->setDataBits(DATA_8);
port->setStopBits(STOP_1);
port->setDtr(false);
port->setRts(false);
Any ideas on how to get this done. I don't necessarily need to use QextSerialPort should someone know of another library that does the trick.
I'm new to C++ and Qt.
UPDATE:
I noticed that if I run a python script that connects to the same port (using pySerial) before running the above code, everything works just fine.
I had a similar problem.
In my case QExtSerial would open the port, I'd see the RX/TX lights on the board flash, but no data would be received. If I opened the port with another terminal program first QExtSerial would work as expected.
What solved it for me was opening the port, configuring the port settings, and then making DTR and RTS high for a short period of time.
This was on Windows 7 w/ an ATMega32u4 (SFE Pro Micro).
bool serialController::openPort(QString portName) {
QString selectPort = QString("\\\\.\\%1").arg(portName);
this->port = new QextSerialPort(selectPort,QextSerialPort::EventDriven);
if (port->open(QIODevice::ReadWrite | QIODevice::Unbuffered) == true) {
port->setBaudRate(BAUD38400);
port->setFlowControl(FLOW_OFF);
port->setParity(PAR_NONE);
port->setDataBits(DATA_8);
port->setStopBits(STOP_1);
port->setTimeout(500);
port->setDtr(true);
port->setRts(true);
Sleep(100);
port->setDtr(false);
port->setRts(false);
connect(port,SIGNAL(readyRead()), this, SLOT(onReadyRead()));
return true;
} else {
// Device failed to open: port->errorString();
}
return false;
}
libserial is an incredible library I use for stand-alone serial applications for my Arduino Duemilanove.
qserialdevice use!
Example:
http://robocraft.ru/blog/544.html
Can you just use a 3wire serial cable (tx/rx/gnd) with no DTR,RTS lines?