QT4 TcpSocket bind问题
转自http://www.cnblogs.com/F-32/archive/2012/03/23/2414204.html
Author F32 (feng32@163.com)
The code is released under the terms of GNU Lesser General Public License version 2.1
Here's the code.
#ifndef Q_BOUND_TCP_SOCKET_H #define Q_BOUND_TCP_SOCKET_H #include <QTcpSocket> /** * \brief The QBoundTcpSocket class adds binding support * to tcp client sockets. * * In Qt 4, it's impossible to bind a tcp client socket to * a specific port or ip address. * * This feature has been added to Qt 5, however with version 4, * it's still possible to do binding while getting convenience from * the Qt framework. * * Note: * * Due to usage of native api, the class currently not supports * platforms other than Linux. If you are familiar with * native programming interfaces like winsock, porting the code * to other operations systems may be just a piece of cake. * * A QBoundTcpSocket object will bind and connect to the server * at the same time, because the only way to work around is to * create a socket, bind, connect to server with native API from the * OS, and then pass the socket to QTcpSocket::setSocketDescriptor * with a connected state. */ class QBoundTcpSocket : public QTcpSocket { public: /** * \brief Bind the socket and then connect to server * * Note: * * Before calling, the socket must be in the unconnected state, * otherwise a value of false is returned. * * Typical usage: * \code * QBoundTcpSocket socket; * if (socket.bindAndConnect("192.168.1.10", 0, "10.0.0.1", 80)) * { * // Now bound and connected * } * else * { * qDebug() << "An error occurred in QBoundTcpSocket::bindAndConnect"; * } * \endcode * * \param localAddr Local IP address (e.g., "10.0.0.10"). * A value of "0.0.0.0" indicates that * the default ip address will be used. * \param localPort Local port (e.g., 12345). * A value of 0 indicates that any port is acceptable. * \param serverAddr IP address of the server (e.g., "10.0.0.1") * \param serverPort Port of the server (e.g., 80) * * \return The return value is true when both binding and connecting * are successful, and false otherwise. */ bool bindAndConnect(const QString &localAddr, quint16 localPort, const QString &serverAddr, quint16 serverPort); }; #endif /* Q_BOUND_TCP_SOCKET_H */
#include "QBoundTcpSocket.h" #ifdef Q_OS_LINUX #include <arpa/inet.h> #endif bool QBoundTcpSocket::bindAndConnect(const QString &localAddr, quint16 localPort, const QString &serverAddr, quint16 serverPort) { #ifdef Q_OS_LINUX int sockfd; int result; struct sockaddr_in localSockAddr; struct sockaddr_in serverSockAddr; bzero(&localSockAddr, sizeof(localSockAddr)); bzero(&serverSockAddr, sizeof(serverSockAddr)); // create socket sockfd = socket(AF_INET, SOCK_STREAM, 0); if( sockfd == -1 ) { qDebug() << "QBoundTcpSocket: Cannot create socket"; return false; } // bind localSockAddr.sin_family = AF_INET; localSockAddr.sin_port = htons(localPort); localSockAddr.sin_addr.s_addr = inet_addr(localAddr.toLocal8Bit().data()); result = bind(sockfd, (struct sockaddr *)&localSockAddr, sizeof(localSockAddr)); if( result == -1 ) { qDebug() << "QBoundTcpSocket: Cannot bind socket"; return false; } // connect serverSockAddr.sin_family = AF_INET; serverSockAddr.sin_port = htons(serverPort); serverSockAddr.sin_addr.s_addr = inet_addr(serverAddr.toLocal8Bit().data()); result = ::connect(sockfd, (struct sockaddr *)&serverSockAddr, sizeof(serverSockAddr)); if( result == -1 ) { qDebug() << "QBoundTcpSocket: Cannot connect to server"; return false; } // set socket descriptor if( !setSocketDescriptor(sockfd, QAbstractSocket::ConnectedState)) { qDebug() << "QBoundTcpSocket: Cannot set socket descriptor"; return false; } return true; #else qDebug() << "QBoundTcpSocket for Windows/Mac OS is not implemented yet"; return false; #endif }