Set a local port to a QTcpSocket
-
Hi,
please, could you post all your working code?
-
Hello,
with startWithoutBindLocal() function the connection is established
but with startWithBindLocal() the connection is not etablished.
I want to realize a connection with startWithBindLocal() because I would like to binding with host port and address.Below the working code
the client side
client_tcp.h
@#ifndef CLIENT_TCP_H
#define CLIENT_TCP_H#include <QtGui/QMainWindow>
#include "ui_client_tcp.h"
#include <QTcpSocket>
#include <QTimer>
#include <Winsock2.h>class cclient_tcp : public QMainWindow
{
Q_OBJECTpublic:
cclient_tcp(QWidget *parent = 0, Qt::WFlags flags = 0);
~cclient_tcp();public slots:
void estConnecte();
void estDeconnecte();
void onTimer();private:
bool startWithBindLocal();
bool startWithoutBindLocal();void stop();
void writeString(QString texte);private:
Ui::cclient_tcpClass ui;QTcpSocket* m_pClient;
bool m_connected;
QTimer* m_pTimer;
};#endif // CLIENT_TCP_H
@
client_tcp.cpp
@#include "client_tcp.h"cclient_tcp::cclient_tcp(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
ui.setupUi(this);
m_connected = false;
m_pClient = NULL;
//startWithoutBindLocal();
startWithBindLocal();
}cclient_tcp::~cclient_tcp()
{
stop();
}bool cclient_tcp::startWithBindLocal()
/*
start the tcp connection with a socket local bind
*/
{
bool ok=false;
WSADATA wsaData;
if( WSAStartup( MAKEWORD( 2, 2 ), &wsaData ) == 0)
{
int handle_socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);// bind to local interface
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_port = htons(2000);
service.sin_addr.s_addr = inet_addr("15.0.0.1");
if(::bind(handle_socket, (SOCKADDR*) &service, sizeof(service)) == SOCKET_ERROR)
{
int e = WSAGetLastError();
qDebug() << "Socket error = " << e;
closesocket(handle_socket);
}
else
{
m_pClient = new QTcpSocket();
if(m_pClient != NULL)
{
// set the socket descriptor to QTcpSocket
bool ok = m_pClient->setSocketDescriptor(handle_socket);connect(m_pClient, SIGNAL(connected()), this, SLOT(estConnecte())); connect(m_pClient, SIGNAL(disconnected()), this, SLOT(estDeconnecte())); m_pTimer = new QTimer(this); connect(m_pTimer, SIGNAL(timeout()), this, SLOT(onTimer())); m_pTimer->start(1000); // connect to server host m_pClient->connectToHost("15.0.0.2", 3000); ok = true;
}
}
}
return ok;
}bool cclient_tcp::startWithoutBindLocal()
{
bool ok=false;
m_pClient = new QTcpSocket();
if(m_pClient != NULL)
{
connect(m_pClient, SIGNAL(connected()), this, SLOT(estConnecte()));
connect(m_pClient, SIGNAL(disconnected()), this, SLOT(estDeconnecte()));m_pTimer = new QTimer(this);
connect(m_pTimer, SIGNAL(timeout()), this, SLOT(onTimer()));
m_pTimer->start(1000);// connect to server host
m_pClient->connectToHost("15.0.0.2", 3000);
ok = true;
}
return ok;
}void cclient_tcp::stop()
{
if(m_pClient != NULL)
{
m_pClient->disconnectFromHost();
delete m_pClient;
}
}void cclient_tcp::estConnecte()
{
m_connected = true;
qDebug("client connected");
}void cclient_tcp::estDeconnecte()
{
qDebug("client deconnected");
}void cclient_tcp::writeString(QString texte)
{
if(m_connected)
{
m_pClient->write(texte.toAscii(), texte.length());
}
}void cclient_tcp::onTimer()
{
writeString("test");
}
@========================================================
the server side
server_tcp.h
@#ifndef SERVER_TCP_H
#define SERVER_TCP_H#include <QtGui/QMainWindow>
#include "ui_server_tcp.h"
#include <QTcpServer>
#include <QTcpSocket>class cserver_tcp : public QMainWindow
{
Q_OBJECTpublic:
cserver_tcp(QWidget *parent = 0, Qt::WFlags flags = 0);
~cserver_tcp();public slots:
void acceptConnection();
void startRead();private:
Ui::cserver_tcpClass ui;
QTcpServer m_server;
QTcpSocket* m_pClient;
};#endif // SERVER_TCP_H
@
server_tcp.cpp
@#include "server_tcp.h"cserver_tcp::cserver_tcp(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
ui.setupUi(this);connect(&m_server, SIGNAL(newConnection()), this, SLOT(acceptConnection()));
bool enListen = m_server.listen(QHostAddress("15.0.0.2"), 3000);
qDebug() << "listen on 15.0.0.2/3000 = " <<enListen;
}cserver_tcp::~cserver_tcp()
{}
void cserver_tcp::acceptConnection()
{
m_pClient = m_server.nextPendingConnection();connect(m_pClient, SIGNAL(readyRead()), this, SLOT(startRead()));
}void cserver_tcp::startRead()
{
char buffer[1024] = {0};
m_pClient->read(buffer, m_pClient->bytesAvailable());
qDebug(buffer);
}@ -
Hi,
as shown "here":http://qt-project.org/doc/qt-4.8/qabstractsocket.html#setSocketDescriptor when you call setSocketDescriptor the socket will be opened by default in ConnectedState you should use QAbstractSocket::UnconnectedState
-
Hi,
Thanks for your response, but the bind is not Ok because the connection is established on a local random port. It is not 2000.
@service.sin_port = htons(2000);
@ -
Hi,
I think you should establish connection using Winsock API and only after you use setSocketDescriptor()
-
Hi,
The connection is etablished now with the good local port, but if i launch a second time the application I have the error 10048 (WSAEADDRINUSE) after the ::connect function. I have to wait a timeout before reuse without error.
Below the code:
@bool cclient_tcp::startWithBindLocal()
/*
start the tcp connection with a socket local bind
*/
{
WSADATA wsaData;
if(WSAStartup( MAKEWORD( 2, 2 ), &wsaData ) == 0)
{
m_handle_socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);// bind to local interface
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_port = htons(2000);
service.sin_addr.s_addr = inet_addr("15.0.0.1");
if(::bind(m_handle_socket, (SOCKADDR*) &service, sizeof(service)) == SOCKET_ERROR)
{
int e = WSAGetLastError();
qDebug() << "Socket bind error = " << e;
// closesocket(m_handle_socket);
WSACleanup();
return false;
}
else
{
m_pClient = new QTcpSocket();
if(m_pClient != NULL)
{
connect(m_pClient, SIGNAL(connected()), this, SLOT(estConnecte()));
connect(m_pClient, SIGNAL(disconnected()), this, SLOT(estDeconnecte()));
connect(m_pClient, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(erreurSocket()));
connect(m_pClient, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(socketStateChanged(QAbstractSocket::SocketState)));m_pTimer = new QTimer(this); connect(m_pTimer, SIGNAL(timeout()), this, SLOT(onTimer())); m_pTimer->start(1000); // connect to server host sockaddr_in server_sock; server_sock.sin_family = AF_INET; server_sock.sin_port = htons(3000); server_sock.sin_addr.s_addr = inet_addr("15.0.0.2"); // connect to the server if(::connect(m_handle_socket, (SOCKADDR*) &server_sock, sizeof(server_sock)) == SOCKET_ERROR) { int e = WSAGetLastError(); qDebug() << "Socket connect error = " << e; //closesocket(m_handle_socket); WSACleanup(); return false; } // set the socket descriptor to QTcpSocket bool ok_desc = m_pClient->setSocketDescriptor(m_handle_socket/*, QAbstractSocket::UnconnectedState*/);
// m_pClient->connectToHost("15.0.0.2", 3000);
return true;
}
}
}
return false;
}
@ -
Hi,
if you don't close a TCP socket, the address will be released only after some minutes. If you close correctly the socket, the problem will disappear.
-
Hello,
The stop function in the destructor should close the socket
because there is no error in this stop function.There is only the closing problem at ::connect function in the startWithBindLocal() .
There is no closing problem with startWithoutBindLocal();Below the source code
tcp_client.h
@#ifndef CLIENT_TCP_H
#define CLIENT_TCP_H#include <QtGui/QMainWindow>
#include "ui_client_tcp.h"
#include <QTcpSocket>
#include <QTimer>
#include <Winsock2.h>class cclient_tcp : public QMainWindow
{
Q_OBJECTpublic:
cclient_tcp(QWidget *parent = 0, Qt::WFlags flags = 0);
~cclient_tcp();public slots:
void estConnecte();
void estDeconnecte();
void erreurSocket();
void socketStateChanged(QAbstractSocket::SocketState state);
void onTimer();private:
bool startWithBindLocal();
bool startWithoutBindLocal();void stop();
void writeString(QString texte);private:
Ui::cclient_tcpClass ui;QTcpSocket* m_pClient;
bool m_connected;
QTimer* m_pTimer;
SOCKET m_handle_socket;
};#endif // CLIENT_TCP_H
tcp_client.cpp
@#include "client_tcp.h"cclient_tcp::cclient_tcp(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
ui.setupUi(this);
m_connected = false;
m_pClient = NULL;
//startWithoutBindLocal();
startWithBindLocal();
}cclient_tcp::~cclient_tcp()
{
stop();
}bool cclient_tcp::startWithBindLocal()
/*
start the tcp connection with a socket local bind
*/
{
WSADATA wsaData;
if(WSAStartup( MAKEWORD( 2, 2 ), &wsaData ) == 0)
{
m_handle_socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);// bind to local interface
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_port = htons(2000);
service.sin_addr.s_addr = inet_addr("15.0.0.1");
if(::bind(m_handle_socket, (SOCKADDR*) &service, sizeof(service)) == SOCKET_ERROR)
{
int e = WSAGetLastError();
qDebug() << "Socket bind error = " << e;
// closesocket(m_handle_socket);
WSACleanup();
return false;
}
else
{
m_pClient = new QTcpSocket();
if(m_pClient != NULL)
{
connect(m_pClient, SIGNAL(connected()), this, SLOT(estConnecte()));
connect(m_pClient, SIGNAL(disconnected()), this, SLOT(estDeconnecte()));
connect(m_pClient, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(erreurSocket()));
connect(m_pClient, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(socketStateChanged(QAbstractSocket::SocketState)));m_pTimer = new QTimer(this); connect(m_pTimer, SIGNAL(timeout()), this, SLOT(onTimer())); m_pTimer->start(1000); // connect to server host sockaddr_in server_sock; server_sock.sin_family = AF_INET; server_sock.sin_port = htons(3000); server_sock.sin_addr.s_addr = inet_addr("15.0.0.2"); // connect to the server if(::connect(m_handle_socket, (SOCKADDR*) &server_sock, sizeof(server_sock)) == SOCKET_ERROR) { int e = WSAGetLastError(); qDebug() << "Socket connect error = " << e; //closesocket(m_handle_socket); WSACleanup(); return false; } // set the socket descriptor to QTcpSocket bool ok_desc = m_pClient->setSocketDescriptor(m_handle_socket/*, QAbstractSocket::UnconnectedState*/);
// m_pClient->connectToHost("15.0.0.2", 3000);
return true;
}
}
}
return false;
}bool cclient_tcp::startWithoutBindLocal()
{
bool ok=false;
m_pClient = new QTcpSocket();
if(m_pClient != NULL)
{
connect(m_pClient, SIGNAL(connected()), this, SLOT(estConnecte()));
connect(m_pClient, SIGNAL(disconnected()), this, SLOT(estDeconnecte()));m_pTimer = new QTimer(this);
connect(m_pTimer, SIGNAL(timeout()), this, SLOT(onTimer()));
m_pTimer->start(1000);// connect to server host
m_pClient->connectToHost("15.0.0.2", 3000);
ok = true;
}
return ok;
}void cclient_tcp::stop()
{
if(::closesocket(m_handle_socket) == SOCKET_ERROR)
{
int e = WSAGetLastError();
qDebug() << "Socket close error = " << e;
}if(WSACleanup() == SOCKET_ERROR)
{
int e = WSAGetLastError();
qDebug() << "Socket WSACleanup error = " << e;
}
if(m_pClient != NULL)
{
m_pClient->disconnectFromHost();
delete m_pClient;
}
}void cclient_tcp::estConnecte()
{
m_connected = true;
qDebug("client connected");
}void cclient_tcp::estDeconnecte()
{
qDebug("client deconnected");
}void cclient_tcp::erreurSocket()
{
qDebug("client socket erreur");
}void cclient_tcp::socketStateChanged(QAbstractSocket::SocketState state)
{
qDebug() << "client socket changed, state=" << state;
if(state == QAbstractSocket::ConnectedState)
{
m_connected = true;
}
}void cclient_tcp::writeString(QString texte)
{
if(m_connected)
{
m_pClient->write(texte.toAscii(), texte.length());
}
}void cclient_tcp::onTimer()
{
writeString("test");
}
@ -
Hi,
are you sure close works properly?
However, you can also specify to reuse address in bind; this prevents to have problem when your application exit in no proper way (for example a crash)
-
Hi,
I think that my application close works properly.
The reuse address with setsockoptions does not give more results.The only way is to change the local port, each time the application reconnects, but I want to keep the same local port.
The only way to set a local port and a reconnection without timeout is to generate my application with Qt 5, is not it ?