С чего начать? Начало, я полагаю.
Я новичок в программировании сокетов. Я хотел дать ему шанс. После исследования я обнаружил, что, похоже, нет стандартной библиотеки сокетов C ++ oop ( было несколько сторонних библиотек , которые могли бы быть oop, но я все равно решил сделать свою собственную потому что, ну, так веселее, так как это в любом случае личный проект), поэтому я решил сделать свой собственный.
Я решил, что моя новая библиотека будет интегрирована с iostream. Конечно, это, вероятно, не очень хорошая идея, обычно , но я подумал: 1) У меня была хорошая причина для этого и 2) это все равно было просто академическим упражнением. Это не помешает, по крайней мере, научиться это делать.
Таким образом, Я немного покопался и придумал такой дизайн:
class NetworkStream : public std::iostream {
public:
// class network streambuff
// should handle the actual writing
class NetworkBuff : public std::streambuf {
private:
SOCKET socket; // I'm working with winsock2, btw
public:
NetworkBuff(SOCKET s);
protected:
// out
virtual std::streamsize xsputn(const char* buffer, std::streamsize size);
virtual std::streamsize overflow(char buffer);
virtual int underflow();
virtual std::streamsize xsgetn(char* buffer, std::streamsize size);
};
// constructors
NetworkStream(SOCKET socket); // sets up the socket in NetworkBuff
virtual ~NetworkStream();
}; // end network stream
Этот объект NetworkStream должен обрабатывать фактическое чтение и запись в сети. Соединение поддерживается кодом более высокого уровня (и я имею в виду объект, который наследуется от NetworkStream). Этот код работает (насколько я могу судить, в любом случае) и не имеет отношения к моему вопросу, поэтому я его опустил. Я просто упоминаю об этом, чтобы вы поняли мой дизайн.
В любом случае, фактическая реализация моего нового объекта потока выглядит примерно так:
// class network streambuff
// should handle the actual writing
//constructor
NetworkStream::NetworkBuff::NetworkBuff(SOCKET s) {
socket = s;
}
// out
std::streamsize NetworkStream::NetworkBuff::xsputn(const char* buffer, std::streamsize size) {
// well, let's send the data
int result = send(socket,buffer,static_cast<int>(size),0);
// if that didn't work, throw an error
if(result == SOCKET_ERROR) throw("Send Failure: " + WSAGetLastError());
// NOTE: I realized after I wrote this that this throw may be useless,
// since I think iostream catches any errors thrown at this level, but
// just in case
// and pass through to streambuff, because, well, it can't hurt
return std::streambuf::xsputn(buffer, size);
}
// basically do the same thing as before...
std::streamsize NetworkStream::NetworkBuff::overflow(char buffer) {
// well, let's send the data
int result = send(socket,buffer,sizeof(buffer),0);
// if that didn't work, throw an error
if(result == SOCKET_ERROR) throw("Send Failure: " + WSAGetLastError());
// and pass through to streambuff, because, well, it can't hurt
return std::streambuf::overflow(buffer);
}
Насколько я могу судить, это работает как шарм. Я прошагал через мой отладчик, и мой xsputn()
был вызван. Так что я могу сделать что-то вроде этого:
std::string data = "Hello, world!";
networkstream << data;
И это называется. Я думаю, что отправлено успешно. Он не проходит через мой отладчик, результат не имеет ошибки. Тем не менее, я еще не проверил его полностью, потому что не работает моя функция приема:
std::streamsize NetworkStream::NetworkBuff::xsgetn(char* buffer, std::streamsize size) {
// well, let's read the data
int result = recv(socket,buffer,static_cast<int>(size),0);
// if that didn't work, throw an error
if(result == SOCKET_ERROR) throw("Receive Failure: " + WSAGetLastError());
// Now this I think is wrong, specifically comparing against SOCKET_ERROR.
// That's not my problem, though. My problem is that this function seems to
// never get called, so a wrong comparison doesn't matter yet anyway
// and pass through to streambuff, because, well, it can't hurt
return std::streambuf::xsgetn(buffer, size);
}
// Now this guy, I'm pretty extra sure is probably wrong, but it's what I got. I
// couldn't find a good example of using underflow, so I did my best from the
// research I did find
int NetworkStream::NetworkBuff::underflow() {
// well, let's read the data
int result = recv(socket,gptr(),sizeof(*gptr()),0);
// if that didn't work, throw an error
if(result == SOCKET_ERROR) throw("Recieve Failure: " + WSAGetLastError());
// and pass through to streambuff, because, well, it can't hurt
return std::streambuf::underflow();
}
Он очень хорошо компилируется. Однако, когда я пытаюсь использовать это:
std::string data = "";
networkstream >> data; // should wait for data on the network
Кажется, будто бы ничего не произошло. Нет, на самом деле, согласно моему отладчику, он, похоже, устанавливает бит сбоя, игнорирует мои практически перегруженные функции и продолжает выполнение, как будто ничего не произошло.
Итак, мой вопрос в одном абзаце: что именно не так с моей функцией underflow / xsgetn, которая приводит к ее сбою и по существу игнорирует мой код? Я уверен, что я делаю что-то не так, но что именно?