2014-10-21 3 views
0

클라이언트 - 서버 환경을 만들고 있는데 UDP를 구현했습니다. 이전에 TCP 연결로 작업하고 테스트 중이었지만 모든 것이 정상적으로 작동했습니다. 이제 클라이언트에서 서버로 패킷을 보내려고하면 일부 필수 입력란이 채워지지 않는 오류가 발생합니다 (나중에 코드 참조). 이전에 작동 한 이후로 왜 이런 일이 일어나고 있는지 전혀 알 수 없습니다.ProtocolBuffer에 필수 필드가 누락되었지만 채워졌습니다.

내가 중요 할 수있는 한 가지는 TCP 소켓과 UDP 소켓의 수신 방법이 다른 스레드에 있다는 것입니다.

하는 TCP는 수신 (의 일부) : 그래서

(서버가 멀티 스레딩을 사용), 여기에 몇 가지 코드의

iResult = recv(m_Connections[t].socket, m_TCPRecvbuf, m_TCPRecvbuflen, 0); 

// Deserialize the data 
MessageID* receivedData = new MessageID(); 
receivedData->ParseFromArray((char*)m_TCPRecvbuf, receivedData->packetsize()); 

나는 한 듯 처음 iResult와 ParseFromArray의 크기 (작업)하지만 데이터 자체에 크기를 넣기 위해 그것을 변경했습니다. (현재되었다하는 receivedData-> PACKETSIZE는())

UDP를 다른 스레드 (의 일부)를 수신 :

iResult = recvfrom(m_UDPListenSocket, m_UDPRecvbuf, m_UDPRecvbuflen, 0, (struct sockaddr *)&address, &addrlen); 
// Deserialize the data 
MessageID* receivedData = new MessageID(); 
receivedData->ParseFromArray((char*)m_TCPRecvbuf, receivedData->packetsize()); 

을이 보내지는 패킷의 제 작성이다

void NetworkInterface::SendLoginData(string username, string password) 
{ 
// Create base message 
// ----------------- 
MessageID message; 
message.set_type(MessageID::Type::MessageID_Type_LOGINDATA); 

// Create logindata 
// ------------------ 
LoginData data = message.logindata(); 
data.set_username(username); 
data.set_password(password); 

// Create packet 
// ---------------------- 
int size = message.ByteSize(); 
void* buffer = malloc(size); 

message.set_packetsize(size); 
message.set_clientid(0); 

message.SerializeToArray(buffer, size); 

if (m_pTCPNetworkingObject != nullptr) 
    m_pTCPNetworkingObject->SendData(buffer, size); 
else 
    printf("NetworkInterface [ERROR]: No connection data was found. Please use CreateConnectionObject() first!\n"); 
} 

가이 후에 준다 오류는 유형이 된 ClientID 및 PACKETSIZE 필드가 누락하지만 당신은 여기에 같이 sendData() 메소드의 사람들은

에 가득 볼 수 있습니다 :

void SendData(void* data, int size) 
{ 
    // SEND DATA 
    int iResult; 
    iResult = send(m_TCPConnectSocket, (char*)data, size, 0); 
    if (iResult == SOCKET_ERROR) 
     printf("send failed with error: %d\n", WSAGetLastError()); 
} 

이것은 내가 제공 할 수있는 모든 정보입니다. 어떤 도움을 주셔서 감사합니다.

1) 직렬화 :

receivedData->ParseFromArray((char*)m_TCPRecvbuf, receivedData->packetsize()); 

당신은 대신 iResult를 사용, 그것은 parseFromArray에 의해 작성되기 전에 packetSize 전화

+0

새 메시지에서'receivedData-> packetsize()'를 호출합니다. 의도적입니까? 'iResult'를 사용해서는 안됩니까? 전체 메시지를 단일 UDP 패킷으로 전송할 수 있습니까? –

+0

어디서 오류가 정확히 발생합니까? 컴파일 오류입니까 아니면 런타임 중입니까? –

+0

@JonSkeet 사실입니다. UDP에 대해 확인하지 않았습니다. 흠, 패킷 화 된 것 ... 나는 그걸 확인해야합니다. o_weisman 런타임에입니다. – Dries

답변

0

여러 문제가 있습니다.

2) LoginData :이 메시지 빈 loginData을의 사본을 읽어

LoginData data = message.logindata(); 

, 당신은 message를 변경하지 않습니다.

LoginData* data = message.mutable_logindata(); 

는 메시지 loginData에 대한 포인터를 내려면 message 내에서 수정할 때 사용합니다.

3) 직렬화 : loginData 설정되어 있지 않기 때문에

int size = message.ByteSize(); 
void* buffer = malloc(size); 

이것이 (빈 메시지의 크기를 사용하여). 그래서 당신은 완전한 메시지를 보내지 않습니다. 모든 속성을 설정 한 후에 ByteSize()으로 전화해야합니다. 이것은 메시지 내의 packetSize와 모순됩니다. 어쨌든 직렬 변환에 사용할 수 없으므로 (1 참조)이 항목을 제거해야합니다.

관련 문제