C++ Socket

Started by
4 comments, last by Evil Steve 15 years, 11 months ago
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]
Advertisement
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
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.
English is not my native language.Sam.
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.
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;        }}
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).

This topic is closed to new replies.

Advertisement