Update: I figured it out! Kind of… I’m not sure how this fixed it, but it did. Instead of using:
NetworkMessage msg;
msg.AddByte(0x01);
sendmessage(msg);
I tried this and it worked(with few changes to some functions)
NetworkMessage* msg = new NetworkMessage();
msg.AddByte(0x01);
sendmessage(msg);
This fixed it, but would still appreciate an explanation from anyone of why this was happening in the first place. Post it as an answer so I can mark it. Thank you.
I’ve been working on a TCP Server but I’ve been having a little problem..
There’s a loop that sends about 600? messages, sending 1 at a time(reading from queued message list).
For some reason, about 200 reach my client without errors, then I get a System.10014 error. Every time on a different message, even though the messages are the same every time. Also, if I just re-send the message after System.10014 error, it works fine. So it’s obvious the message is not the problem. But I have no idea what is. I’ve spend the entire day yesterday trying to figure it out and still no luck. So here I am. Again.
void outputMessage(NetworkMessage& msg, bool forceTrue = false)
{
if(!connectionLocked || forceTrue) {
connectionLocked = true;
std::cout << "Message: ";
char* buf = msg.getOutputBuffer();
for (int i = 0; i < msg.size(); i++){
std::cout << (buf[i] + 0) << ":"; //Never any errors
}
boost::asio::async_write(socket_, boost::asio::buffer(msg.getOutputBuffer(), msg.size()),boost::bind(&Session::handle_write, shared_from_this(), msg, boost::asio::placeholders::error));
}
else {
//Queue message
_msgqueue.push_back(msg);
}
}
void handle_write(NetworkMessage& msg, const boost::system::error_code& error)
{
if (error)
{
cout << "Error: " << error << endl;
outputMessage(msg, true); //works, even though it's the same message
}
else {
if(_msgqueue.size() != 0){
//cout << "Sending queued message #" << _msgqueue.size() << endl;
outputMessage(_msgqueue.front(), true);
_msgqueue.pop_front();
}
else
connectionLocked = false;
}
}
This is the code for my send function basically. It works fine, usually. For some reason when I’m sending a lot of messages in a row, this error(System.10014) happens. I tried reading about the error in Winsock, but I really don’t understand it(it says something about invalid pointers but I’m pretty sure the message is valid because sending it again works just fine?). And I have little experience with programming and especially with C++ and pointers so I’m having a little trouble.
The loop that generates the messages goes a little like this. I verified that the X and Y are valid, so I’m pretty sure the problem isn’t there.
map->cursor = map->begin;
while(map->cursor != NULL)
{
//I'm not sure if pointers like this are supposed to be deleted?
//I suck when it comes to memory management, and most other things :D
Tile* tile = map->cursor->tile;
if(tile){
NetworkMessage msg;
msg.AddByte(0x03);
msg.AddByte(tile->posx);
msg.AddByte(tile->posy);
msg.AddByte(1);
msg.AddByte(2);
outputMessage(msg);
}
else
break;
map->cursor = map->cursor->next;
}
Also, this might not seem relevant but if I try changing my outputMessage to this:
void outputMessage(NetworkMessage& msg)
{
boost::asio::async_write(socket_, boost::asio::buffer(msg.getOutputBuffer(), msg.size()),boost::bind(&Session::handle_write, shared_from_this(), msg, boost::asio::placeholders::error));
}
void handle_write(NetworkMessage& msg, const boost::system::error_code& error)
{
if (error)
{
cout << "Error: " << error << endl;
}
}
I don’t get any errors, but the messages sent are all clones. So the 600 messages all look the same. It seemed weird, so I thought it may be relevant to the problem I’m having now.
Also here’s NetworkMessage.h, I also posted it on pastebin you can see in the comments.
#ifndef _NETWORK_MESSAGE_H
#define _NETWORK_MESSAGE_H
class NetworkMessage
{
public:
enum { header_length = 2 };
enum { max_body_length = NETWORKMESSAGE_MAXSIZE - header_length};
NetworkMessage()
{
buf_size=0;
m_ReadPos=header_length;
}
void AddByte(char byte_)
{
if (!canAdd(1)) return;
data_[m_ReadPos++] = byte_;
//data_[m_ReadPos] = '\0';
buf_size++;
}
uint16_t PeekU16(){
return (data_[1] | uint16_t(data_[0]) << 8);
}
uint16_t GetU16(){
m_ReadPos += 2;
return (data_[m_ReadPos+1]) | (uint16_t(data_[m_ReadPos]) << 8);
}
uint8_t GetByte(){return data_[m_ReadPos++];}
char* getBuffer()
{
return (char*)&data_[m_ReadPos];
}
char* getOutputBuffer()
{
writeMessageLength();
return (char*)&data_[0];
}
void setMessageLength(uint16_t v)
{
buf_size=v;
}
void writeMessageLength()
{
*(uint8_t*)(data_) = (buf_size >> 8);
*(uint8_t*)(data_+1) = buf_size;
}
void reset()
{
m_ReadPos = 0;
buf_size = 0;
}
uint16_t size(){return buf_size+header_length;}
protected:
inline bool canAdd(uint32_t size)
{
return (size + m_ReadPos < max_body_length);
};
private:
uint8_t data_[NETWORKMESSAGE_MAXSIZE];
uint16_t buf_size;
uint16_t m_ReadPos;
};
#endif //_NETWORK_MESSAGE_H
Update: Alright so, came across something weird…
function error_func(NetworkMessage& msg){
cout << &msg << endl; //0x2882e8(not 0x274c0e8)
send(msg.getOutputBuffer(), msg.size(), error_func, msg); //no error
}
cout << &msg << endl; //0x274c0e8
send(msg.getOutputBuffer(), msg.size(), error_func, msg); //error system.10014
Obviously this isn’t real code, but you get the idea… I guess this is why re-sending it from error_func works. The problem might be in NetworkMessage after all. I’ve been messing in all the wrong places all this time 😀 Still need help though, lol.
Would really appreciate any help, I’m stuck. Thanks for reading if you got this far..
the buffer passed to
async_writeneeds to be valid throughout the duration of the operation. The documentation is very explicit hereYou’ve passed a pointer that is no longer valid when the
NetworkMessageobject is destroyed, which I am guessing is before theasync_writeoperation completes. TheNetworkMessageobject is copied when passed to yourhandle_write()completion handler.