Sign in to follow this  
TigerSam

C++ Socket

Recommended Posts

Hi all, I have a basic win32 client and server which i am trying to pass messages between. I set both of them up with a socket and set the server into listening mode. when i send a message to to the server from the client it recieves it fine and displays it. if i try to send another i get the following errors: server: successful WSA Startup not done (WSA 10093) client: connection reset by peer (WSA 10054) My question is when should i be trying to reuse the socket for future messages or should i be creating a new socket for every message. i would have thought once a connection is established that all communications are done through that socket. in which case how do i reuse the socket? my server code is within a thread and is:
this->CreateSocket(); // binds socket and sets to listening
	
while(this->threadIsRunning())
{	
	this->accept() //message will be accepted and printed to screen
}
WSACleanup();
Any ideas or pointers would be helpful Cheers [Edited by - TigerSam on May 10, 2008 7:18:47 AM]

Share this post


Link to post
Share on other sites
Ok, it seems in a multi threading environment calling WSACleanup() results in a socket error

Quote:
In a multithreaded environment, WSACleanup terminates Windows Sockets operations for all threads.


Im currently searching for an alternative assuming im going about my problem in the correct way. If anybody is more wise than me id apprechiate any help.

Cheers

Share this post


Link to post
Share on other sites
Why are you calling WSACleanup here ? Once you have called this function, all subsequent operations on sockets will fail, since the purpose of the WSACleanup function is to terminates use of the Winsock 2 DLL in the entire process.

Share this post


Link to post
Share on other sites
Quote:
set the server into listening mode [...] should i be trying to reuse the socket for future messages
Yes, because this one socket is the one that's listening, and you get an individual per-connection socket back from accept().

Quote:
Why are you calling WSACleanup here ? Once you have called this function, all subsequent operations on sockets will fail
Yup, that is very likely your problem. You should call WSAStartup() and WSACleanup() once at the very beginning and at the very end of your program.

Share this post


Link to post
Share on other sites
Ok, cheers guys i have removed the calls to WSACleanup() and placed one after the thread has finished its loop instead. I can still only recieve the first message though. Here is my server code for the functions previously posted


void NetPacket::CreateSocket()
{
// Create Version Identifier
WORD wVersionRequested = MAKEWORD(2,0);
// Start up windows sockets
WSADATA wsaData;
if(WSAStartup(wVersionRequested, &wsaData))
{
cerr<<"Socket Initialisation Failed"<<endl;
}

//Create Socket Data Space
peer.sin_family = AF_INET;// sockaddr peer class member
peer.sin_port = htons(2001);
peer.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

// Create a socket
_socket = socket(AF_INET, SOCK_STREAM, 0); // _socket class member
if(_socket == INVALID_SOCKET)
{
cerr<<"Create Socket Failed"<<endl;
}

else if (bind(_socket, (sockaddr *)&peer, sizeof(peer))==SOCKET_ERROR)
{
cerr << "Bind failed with " << WSAGetLastError() << endl;
}
else if (listen(_socket, 5)==SOCKET_ERROR)
{
cerr << "Listen failed with " << WSAGetLastError() << endl;
}
}



bool NetPacket::accept()
{
char buffer[1000];
int bufferSize = sizeof(buffer);
int bytesRead = 0;

SOCKET s = accept(_socket, NULL, NULL);
cout<<"Passed Accept "<<_socket<<endl;
if (s==INVALID_SOCKET)
{
cerr << "Accept failed with " << WSAGetLastError() << endl;
return false;
}
else if (recv(s, buffer, bufferSize, 0)==SOCKET_ERROR)
{
cerr << "Receive failed with " << WSAGetLastError() << endl;
return false;
}
else
{
cout << "Message= " << buffer << endl;
return true;
}
}


Share this post


Link to post
Share on other sites
You're using TCP (SOCK_STREAM), which doesn't have a concept of messages. You push bytes in one end, and they come out the other.

If you send two messages (structures, or strings, or whatever), then they might end up being read in one recv() on the server, or it might need two recv() calls, or it might need three or more.

If you need to send messages this way, you usually send a 8 or 16-bit value indicating the length of the message, then the data itself. The recv()ing side can then read the size and know how many bytes to expect for the message itself.

EDIT: In this case, if you send two null-terminated strings, it's entirely possible they both get read in a single recv() call, and then when you display the message, you only see the first one because of the null terminator at the end of it.
You can check if that's the case by seeing what recv() returns - if it's the length of both your messages together, you know that's happened (In which case you'll want to do what I described above).

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this