2014-07-25 2 views
0

저는 프로그램을 작성 중이며 한 번에 여러 클라이언트 연결을 처리 할 수 ​​있어야하는 서버가 있습니다. 서버 생성자에서서버에있는 여러 사용자의 연결 처리

:

Server::Server(QObject* parent): QObject(parent) 
{ 
    connect(&server, SIGNAL(newConnection()), //server is a QTcpServer object 
      this, SLOT(acceptConnection())); 
    qDebug() << "[" << currentTime() << "] " << "Server started."; 
    server.listen(QHostAddress::Any, PORT_NUMBER); 
    qDebug() << "[" << currentTime() << "] " << "Server listening."; 
} 

acceptConnection 슬롯 :

void Server::acceptConnection() 
{ 
    client = server.nextPendingConnection(); //client is a QTcpSocket* object 

    connect(client, SIGNAL(readyRead()), //When there is data to be read 
    this, SLOT(startRead())); 
} 

startRead 슬롯 I는 Qt는 라이브러리를 사용하고

, 그래서 나는이 같은 새로운 연결을 처리 :

void Server::startRead() 
{ 

    char serverReceiveBuf[65536]; //A buffer for the data sent to the server 
    client->read(serverReceiveBuf, client->bytesAvailable()); 
    handleConnection(serverReceiveBuf); //Do something with that data 
} 

조금 길기 때문에 질문에 필요하지 않다고 생각하여 handleConnection 기능을 제공하지 않을 것입니다.

내 대기 시간이 문제입니다. 한두 명의 사용자가 있다면 괜찮습니다. 하지만 많은 동시 사용자를 테스트하지 않았습니다. 클라이언트가 보낸 데이터가 서버의 데이터와 일치하는지 확인하도록 서버에 요청하는 동기화 신호가 클라이언트에서 보냅니다. 250 밀리 초마다이 요청을 보내므로 몇 명의 동시 사용자가 있으면 동기화 요청을 보내는 다른 클라이언트 때문에 클라이언트가 250 밀리 초마다 너무 오래 기다리는 결과를 초래할 수 있습니다.

적어도 그것이 내가 믿는 것입니다. Qt는 꽤 강력하지만, 신호를 받았을 때 연결을 처리하기 위해 새로운 스레드가 자동으로 만들어 지는지 확실하지 않습니다. 내가 잘못 본 것이 아니라면, 내가 처리하는 현재의 방식은 큐잉을 포함한다. 그래서 서버가 신호를 받으면 수신 된 순서대로 요청을 처리 할 것이다. 클라이언트가 연결을 종료 할 때까지 client->close()으로 전화하지 않으므로 client = server.nextPendingConnecting();이 호출되면 client은 클라이언트가 프로그램을 종료 할 때까지 항상 존재합니다.

정기적으로 사용자가 동기화 요청을 자주 보내도록하기 때문에 여러 연결을 처리하는 좋은 방법입니까? 그렇지 않다면 연결을 어떻게 처리해야합니까?

+0

새로운 연결을 자동으로 처리하기 위해 새 스레드를 시작하는 것은 매우 비생산적인 일입니다. 당신은'QThread :: idealThreadCount'보다 더 많은 CPU 바운드 쓰레드를 원하지 않습니다. –

답변

0

많은 동시 사용자를 테스트하지 않았습니다.

당신은 Qt는,하지만 그것을 테스트하지 않고, 당신은 특히 하드웨어로, 그 한계가 무엇인지 않을거야 지원할 수있는 클라이언트의 수를 의심 온 실행 여기에 꽤 큰 차이를 만들 수 있습니다 .

몇 백 개의 동시 연결이 있고 각각은 문제없이 데이터를 지속적으로 보내고 받지만 설정은 당신과 다를 수 있습니다.

서버를 설정하는 방법에 관해서는 제공하는 코드에서 즉시 나타나는 문제가 하나 있습니다. startRead() 함수에서 수신 된 데이터가이 시점에서 불완전 할 수 있음을 알아야합니다.

전체 메시지를 받았을 때를 알아야합니다. 가장 간단한 방법은 각 메시지 앞에 메시지 크기를 바이트 단위로 추가 한 다음 메시지의 시작 부분에서 전체 메시지가 나타날 때까지 크기를 읽고 버퍼에 데이터를 계속 추가하는 것입니다. 그런 다음 handleConnection을 호출하십시오.

+0

내 주된 관심사는 서버의 병목 현상이 서버 하드웨어이거나 나쁜 코드를 작성했기 때문입니다. 'startRead()'변경을 위해서 나는 클라이언트로부터'QByteArray'를 사용하여 데이터를 보낸다. 그래서 배열의'size()'를 먼저 보낼 수있다. 어떻게 서버가'size()'바이트를 먼저 수신 할 때까지 기다려야합니까? read()의 두 번째 매개 변수는 읽을 바이트 수를 알고 있지만, 나머지 데이터를 읽지 않고 들어오는 데이터의 크기 만 먼저 읽도록하려면 어떻게해야합니까? 메시지 크기로 int를 보내면'read (messageSize, 4)'를 사용할 수 있습니까? – Lighthat

+0

서버는 대기하지 않고 readyRead를 종료하고 더 많은 데이터를 사용할 수있을 때를 반환합니다. 따라서 전체 메시지가 수신되면 멤버 또는 정적 변수 (QByteArray)의 데이터를 버퍼링하고 handleConnection을 호출해야합니다. – TheDarkKnight

관련 문제