• 5418阅读
  • 3回复

求助一个非常诡异的TCP问题!!拜托了!! [复制链接]

上一主题 下一主题
离线16234655
 
只看楼主 倒序阅读 楼主  发表于: 2011-05-23
本人是新手小白一枚,作为练手,我试着写了一篇实现两个客户端实时交换数据的服务器。
由于写的很简单,所以没分文件,全在一个main里面了。


在定义TCPsocket类的时候,我想用到信号和槽,于是在类的定义时加了Q_OBJECT。编译通过,但是链接马上就出现了“不能识别外部符号”之类的奇奇怪怪的错误,把Q_OBJECT去掉之后,又可以运行了。
天啊~~搞到我纠结无比,烦恼无比,求大家帮忙帮忙!!!


#include <QtGui>
#include <QtCore/QCoreApplication>    
#include <QTcpServer>    
#include <QTcpSocket>    
#include <QThread>    
#include <QObject>
#include<vector>








int times = 0 ;
int max_score = 0 ;
int receive_count;
int connect_count;
int m_fd ;
int score;


int start_mark = 0 ;
int start_time = 0 ;
std::vector<int> ID_mark ;
//////////////////////////////////////////////////////////
class TcpSocket : public QTcpSocket    
{  
    //void updateClientss( QString,QString ); ///////无法解析?无法解析?
Q_OBJECT
signals:
        void enddd();
private:
    QReadWriteLock lock;
//    void end( ) ;
public :
    void dataReceived() ; /////在这儿被引用,对啊?
    void updateClients( QString,QString );
};    //socket 的类,主要是要用到他的信号跟槽
////////////////////////////////////////////////////////
QList< TcpSocket *> SocketList ;


class ServerThread:public QThread    
{    


public:    
    ServerThread(int fd, QObject *parent);    
    void run();
    //void retn() ;
private:    
    //new add


    QReadWriteLock lock;
};    


ServerThread::ServerThread(int fd, QObject *parent     ):QThread(parent)    
{    
    m_fd = fd;


    int k = m_fd ;
  
    ID_mark.push_back( k ) ;




    lock.lockForWrite();
    lock.unlock();
}    




  
void TcpSocket::dataReceived( )  //收到客户端的信息
{
        QDataStream in(this);
         in.setVersion(QDataStream::Qt_4_3);
  
       QString flag ;
       QString data ;


       in >> flag ;
       // 首先是开始游戏的判断。
       in >> data ;


       emit enddd( );  //传送到判断 + 传送函数 //////就是这儿说无法解析,一旦发送就无法解析,肿马了?!到底是肿马了?!


}


void TcpSocket::updateClients( QString flag , QString data )  //收到客户端的信息进行判断
{  
    TcpSocket* socket = this ;
           if( flag == "start_the_game" )
    {  
        QByteArray block_3;
        QDataStream out_3(&block_3, QIODevice::WriteOnly);
        out_3.setVersion(QDataStream::Qt_4_3);
        lock.lockForWrite();    
        ++(start_mark);
        qDebug("I'm Here11111111");
        forever
        {                  
            if(start_mark==2)
            {  
                QString start_game(tr("start_game")) ;
                out_3<<start_game ;
                out_3<<start_game ;
                start_time ++ ;
                lock.unlock();
                break ;
            }
    }
        qDebug("I'm Here222222222222");
        out_3.device()->seek(0);
        socket->write(block_3);
    


    if ( start_time ==2 )
    {
        start_time = 0 ;
        start_mark = 0 ;
    }


    //out<<secret;


    //*max_score=0;
    } //if
       qDebug("I'm H333333333333");




    if( flag == tr("end_the_game") )  //关键字: 游戏结束
    {  


        bool ok(false);                //QString转成int
        score= QString(data).toInt(&ok);


        lock.lockForWrite();
        max_score=max_score>score? max_score:score;
        lock.unlock();


    /*  
        等待数据写完,不加这个函数,接收方总是只能接收到空数据,长度为0  
    */  
    //qDebug("I'v send the data");  
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_3);
    lock.lockForWrite();    
   ++(connect_count); //加1在这儿进行!!!!!利用上锁,先让socket2先读到connect_count,不然socket1会先抢到 == 2 的信号退出清0,socket2死循环
    forever
    {  
        if(connect_count==2)
        {    
            if(score==max_score)
                out<<tr("You win");
            else if(score<max_score)
                out<<tr("Sorry, you lose");
            times ++ ;
            lock.unlock();
            break;
        }
    }
    if( times == 2)
    {
          max_score=0;
          connect_count=0; //清零在最后!!先退出循环即可
          times = 0 ;
    }


    out.device()->seek(0);    
    socket->write(block);


    } //end_the_game
    
    
    
    if( flag == "translate_data" )   //关键字,下标发生改变(客户端自加对方分数1)
    {     qDebug("I'm Here3translate_data333");
          QByteArray block_2;
          QDataStream out_2(&block_2, QIODevice::WriteOnly);
          out_2.setVersion(QDataStream::Qt_4_3);


          QString mes("location_imformation") ;
          //socket->waitForReadyRead(-1);   //接        
          // int location ;
          // in >> location ;


           //QString str_location=QString::number( location );


           for(int i=0;i<SocketList.count();i++)        /*这里给对方送去改变的值*/
         {
            QTcpSocket *item= SocketList.at(i);
            if(ID_mark != m_fd)
            {
                out_2 << mes <<data ;
                item->write(block_2);
                out_2.device()->seek(0);              
            }    
          qDebug("I'm He3");
            
    }


    } //the location information
    } //发送到客户端的函数






void ServerThread::run()    
{    
    /* 在这个进程里,读取数据,写出数据 */  
    qDebug("I'm Here");    
     TcpSocket socket_np ;
     TcpSocket *socket = &socket_np;
    //*socket = socket_np.retn() ;
    qDebug("I'm Here11111111");  
    /* 根据手册要这么使用 */  
    if (!  (socket_np.setSocketDescriptor( m_fd ))  )
    {  
        qDebug("Socket error!");    
        return;    
    }  
    qDebug("I'm Here11111111");  
    
    SocketList.append(socket) ;


    connect(socket, SIGNAL(readyRead()),socket, SLOT(dataReceived( )));      //没有这个槽?


    //connect(socket,SIGNAL(updateClientss(QString,QString,TcpSocket*)),socket,SLOT(updateClients(QString,QString)));


}    


class Server : public QTcpServer    
{    


public:    
    Server();    




private:    
    /* 当产生一个新的连接的时候,会调用这个函数  
       所以可以在我们定义的类中,把它改写覆盖掉,  
       继承来的父类,这个函数是虚函数  
     */  
    void incomingConnection(int sockDescriptor);    
};    




Server::Server():QTcpServer()    
{    
}    




void Server::incomingConnection(int sockDescriptor)    
{    
    /* 在这里面开辟一个线程来处理连接 */  
    ServerThread *thread = new ServerThread(sockDescriptor, this);    
    /*connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));    */
    thread->start();    
}    
  


int main(int argc, char *argv[])    
{    
    QApplication a(argc, argv);    
    Server server;    
    /* 监听了所有网络接口,6178端口 */  
    if ( !server.listen(QHostAddress::Any, 6178)) {    
        qCritical("Cannot listen to port 6178.");    
        server.close();    
        return 1;    
    }  


    QPushButton quitButton(QObject::tr("&Quit"));
    quitButton.setWindowTitle(QObject::tr("Trip Server"));
    QObject::connect(&quitButton, SIGNAL(clicked()),
        &a, SLOT(quit()));
    quitButton.show();


    return a.exec();    
}  



离线dbzhang800

只看该作者 1楼 发表于: 2011-05-23
离线16234655
只看该作者 2楼 发表于: 2011-05-23
对2L前辈的热心解答表示,不胜感激、不胜感激。

我看了你所给的网址的介绍,顿时明白不少,谢谢!

不过由于本人接触socket函数以及QT才不到一周,所以对网站里面的解答还是不大明白,特别是moc widget.h -o moc_widget.cpp,在VS2008里面具体要怎么用吶?
离线16234655
只看该作者 3楼 发表于: 2011-05-24
问题解决了。
其实VS2008是会自动调用MOC的,但是只是适用于头文件,class定义宏的时候,千万要把class的定义独立出来,作为一个头文件,在main里面包含就好。
快速回复
限100 字节
 
上一个 下一个