【发布时间】:2013-12-13 09:22:00
【问题描述】:
您好,我的套接字服务器和客户端有问题。
问题在于,当我非常快速地发送消息时,它们会混淆。当我向他们发送每秒 1 条消息时,一切运行良好,但是当我每 40 毫秒向他们发送 1 条消息时,它们就会混淆。
这是我的接收代码:
std::string* AteneaClient::readSocket () {
std::string finalString = std::string("");
int size = MSG_SIZE;
bool receiving = true;
int timesBufferInc=0;
while (receiving) {
std::string temporalString;
//create an empty buffer
char* RCV_BUFFER = (char*) malloc (size* sizeof(char));
for(int i=0;i<size;i++){
RCV_BUFFER[i]=' ';
}
RCV_BUFFER[size-1]='\0';
int result = recv(sock,RCV_BUFFER,size-1,NULL);
if ( result== SOCKET_ERROR ) {
free(RCV_BUFFER);
return NULL;
}
else if(result<size-1){
receiving=false;
}
temporalString = std::string(RCV_BUFFER);
finalString+=temporalString;
}
return new std::string(finalString);
}
这是我的发送代码:
int sendThread(void* data){
SND_THREAD_DATA* parameters =(SND_THREAD_DATA*)data;
SOCKET* individualSocket = parameters->individualSocket;
std::string * message = parameters->message;
char RCV_BUFFER[MSG_SIZE];
std::string converter;
std::cout <<"(!)Thread: Iniciando sendThread Individual.."<<std::endl;
SOCKET default_socket = *individualSocket;
bool running=true;
while(running){
int length=message->length();
char *cstr = new char[length + 1];
strcpy(cstr, message->c_str());
if(::send(*individualSocket,cstr,length + 1,NULL)==SOCKET_ERROR){
logSendError();
running=false;
}
delete cstr;
Sleep(SLEEPTIME);
}
}
这是我设置套接字时的代码:
void AteneaClient::startUp(){
int iResult = 0;
iResult = WSAStartup(MAKEWORD(2, 2), &WinSockData);
if (iResult != NO_ERROR) {
wprintf(L"(!)Main:WSAStartup() failed with error: %d\n", iResult);
return;
}
ADDR.sin_addr.s_addr= inet_addr(IP);
ADDR.sin_family = AF_INET;
ADDR.sin_port = htons(PORT);
sock = socket(AF_INET,SOCK_STREAM,0);
running=true;
}
有人知道为什么套接字消息会混淆吗?
谢谢!
编辑:
这是我目前使用 Maxim cmets 改进的接收方法:
std::string* AteneaClient::readSocket () {
int HEADER_SIZE=4;
std::string finalString = std::string("");
int sizeFirstBuffer = HEADER_SIZE*sizeof(char);
char* RCV_BUFFER=(char*) malloc(sizeFirstBuffer+1);
//clean new buffer
for(int i=0;i<HEADER_SIZE;i++){
RCV_BUFFER[i]=' ';
}
RCV_BUFFER[sizeFirstBuffer]='\0';
int result = recv(sock,RCV_BUFFER,sizeFirstBuffer,NULL);
//cout << "The Size to read is:" <<RCV_BUFFER << endl;
//now i create a buffer with that size
int sizeThatIHaveToRead= atoi(RCV_BUFFER);
int sizeSecondBuffer = sizeThatIHaveToRead*sizeof(char);
char* RCV_BUFFER_SECOND=(char*) malloc(sizeSecondBuffer+1);
//clean new buffer
for(int i=0;i<sizeSecondBuffer;i++){
RCV_BUFFER_SECOND[i]=' ';
}
RCV_BUFFER_SECOND[sizeSecondBuffer]='\0';
result = recv(sock,RCV_BUFFER_SECOND,sizeSecondBuffer,NULL);
//cout << "RCV_BUFFER_SECOND:" <<RCV_BUFFER_SECOND << endl;
finalString+=RCV_BUFFER_SECOND;
return new std::string(finalString);
}
【问题讨论】:
-
套接字是 TCP (
SOCK_STREAM) 还是 UDP (SOCK_DGRAM) 套接字?它是阻塞套接字还是非阻塞套接字? -
它是一个 TCP 套接字。 SOCK_STREAM
-
你没有使用recv的返回值,这是一个常见的错误。
-
返回值表示接收到的确切字节数。 linux.die.net/man/2/recv 如果不使用该数字,您将无法知道获得了多少字节。如果你刚刚得到第一个字节怎么办?
-
我不完全确定“混合”的定义是什么,但是要在 TCP 上执行基于消息的 I/O(而不是基于流的 I/O),您需要对消息进行框架化,这是一个非常简单的示例:blogs.msdn.com/b/joncole/archive/2006/03/20/555721.aspx
标签: c++ multithreading sockets winsock winsock2