我在用C++编程的套接字应用程序遇到麻烦。我正在使用Windows XP上的Bloodshed Dev-Cpp进行编程。我创建了一个用于处理所有消息传输的类,并拥有一个客户端和服务器程序,它们都使用该类来处理其服务。该应用程序本身非常基础,我唯一的目的就是使所有这些工作正常进行。
用于发送消息的客户端,其工作方式与我期望的一样。如果我的服务器正在运行,则发送消息时没有任何错误。如果它没有运行,将传递一个错误。但是我的服务器不断接受奇怪的胡言乱语。总是相同的数据。当它收到消息时没有任何作用。如果我让我的客户尝试识别服务器,则它会变得乱七八糟。
我在这里包括了我的源代码。链接器还引入了两个额外的参数:-lwsock32和Dev-Cpp随附的库libws2_32.a。
这是我的Messager类的标题:
#ifndef MESSAGER
#define MESSAGER
#include <string>
class Messager{
private:
int sendSocket;
int listenSocket;
public:
void init(void);
bool connect(std::string ip, std::string port);
bool bind(std::string port);
void listen(void);
void send(std::string message);
std::string receive(void);
};
#endif
这些是我对Messager类的定义:
#include "Messager.h"
#include <winsock2.h>
#include <sys/types.h>
#include <ws2tcpip.h>
#include <windows.h>
void Messager::init(void){
WSADATA wsaData;
WSAStartup(MAKEWORD(1,1), &wsaData);
}
bool Messager::connect(std::string ip, std::string port){
struct addrinfo hints;
struct addrinfo *res;
bool success = false;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
getaddrinfo(ip.c_str(), port.c_str(), &hints, &res);
sendSocket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
success = ::connect(sendSocket, res->ai_addr, res->ai_addrlen) != -1;
freeaddrinfo(res);
return success;
}
bool Messager::bind(std::string port){
struct addrinfo hints, *res;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
getaddrinfo(NULL, port.c_str(), &hints, &res);
listenSocket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if(listenSocket == INVALID_SOCKET){
return false;
}
if(::bind(listenSocket, res->ai_addr, res->ai_addrlen) == -1){
return false;
}
return true;
}
void Messager::listen(void){
::listen(listenSocket, 10);
}
int Messager::send(std::string message){
const std::string terminator = "\r\n";
std::string realMessage;
int size = 0;
int totalSent = 0;
realMessage = message;
realMessage += terminator;
size = realMessage.size();
totalSent = ::send(sendSocket, realMessage.c_str(), size, 0);
if(totalSent == 0 || totalSent == -1){
return 0; // There must be an error, 0 means it is an error
}
// This statement keeps adding the results of ::send to totalSent until it's the size of the full message
for(totalSent = 0; totalSent < size; totalSent += ::send(sendSocket, realMessage.c_str(), size, 0));
return totalSent;
}
// This function has been updated a lot thanks to @Luke
std::string Messager::receive(void){
const int bufferSize = 256;
const std::string terminator = "\r\n";
char buffer[bufferSize];
int i = 0;
int received = 0;
std::string tempString;
size_t term = 0;
for(i = 0; i < bufferSize; i++){
buffer[i] = 0;
}
received = ::recv(listenSocket, buffer, bufferSize, 0);
tempString = buffer;
term = tempString.find(terminator);
if(term != -1){ // Already have line
line = tempString;
}
while(received != -1 && received != 0){ // While it is receiving information...
// Flush the buffer
for(i = 0; i < bufferSize; i++){
buffer[i] = 0;
}
::recv(listenSocket, buffer, bufferSize, 0);
tempString += buffer;
term = tempString.find(terminator);
if(term != -1){ // Found terminator!
return tempString;
}
}
throw 0; // Didn't receive any information. Throw an error
}
关于可能发生的事情的任何想法将不胜感激。如有必要,我可以发布服务器和客户端使用的代码,但是我可以给出一个大致的概述:
服务器:
客户:
提前致谢。
最佳答案
我看到两个问题。
通常,这看起来像以下内容(全部来自内存,因此可能存在一些小错误,但这只是要点):
bool Message::Receive(std::string& line)
{
// look for the terminating pair in the buffer
size_t term = m_buffer.find("\r\n");
if(term != -1)
{
// already have a line in the buffer
line.assign(m_buffer, 0, term); // copy the line from the buffer
m_buffer.erase(0, term + 2); // remove the line from the buffer
return true;
}
// no terminating pair in the buffer; receive some data over the wire
char tmp[256];
int count = recv(m_socket, tmp, 256);
while(count != -1 && count != 0)
{
// successfully received some data; buffer it
m_buffer.append(tmp, count);
// see if there is now a terminating pair in the buffer
term = m_buffer.find("\r\n");
if(term != -1)
{
// we now have a line in the buffer
line.assign(m_buffer, 0, term); // copy the line from the buffer
m_buffer.erase(0, term + 2); // remove the line from the buffer
return true;
}
// we still don't have a line in the buffer; receive some more data
count = recv(m_socket, tmp, 256);
}
// failed to receive data; return failure
return false;
}
关于c++ - Winsock recv()和accept()的问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1960038/