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
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值