• Advertisement

Archived

This topic is now archived and is closed to further replies.

Server code driving me crazy

This topic is 5464 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm currently creating a non-blocking server class that using winsock2, but I'm having some problems. I've read an article and used code from a mud as a reference. Maybe I don't know enough about it yet, but I just can't seem to figure out what's wrong. The code isn't commented much at all, but I hope someone can figure it out. Here it is. NonBlockingServer.h
#include "GlobalDefs.h"
#include "GameWorld.h"
#include <winsock2.h>

class CClient
{
public:
	CClient();

	CCharacter *m_pChar;

	sockaddr_in m_sinClient;
	int m_nSinSize;
	SOCKET m_sockClient;

	char *m_byteRecvData;
	char *m_byteSendData[10];
	int m_nSendDataSize[10];

	CClient *m_pNextClient;
	CClient *m_pPrevClient;

	void Send(char *byteData);
	void Send(char *byteData, int nDataSize);
};

class CNonBlockingServer
{
public:
	CNonBlockingServer(unsigned int nPort = 4000, unsigned int nMaxClients = 1);
	~CNonBlockingServer();
	
//private:
	WSADATA m_wsData;			//winsock init data
	sockaddr_in m_sinServer;	//server socket info	
	int m_nSinSize;				//size of server socket info
	SOCKET m_sockServer;		//handle to socket

	unsigned int m_nMaxClients;
	fd_set m_fdRecv,
		   m_fdSend,
		   m_fdError;  //sets of sockets to gather info from

public:
	CClient *m_cClients;
	unsigned int m_nNumClients;
	int m_nNumSocksRdy;

	void PollSockets();
	void ReceiveData();
	void SendData();
	void GetData(CClient *pClient, char *szReturn)  //must be changed for non-text data
	{
		strcpy(szReturn, pClient->m_byteRecvData);  
		*pClient->m_byteRecvData = '\0';
	}
	void DisconnectClient(CClient *pClient);
};
 
NonBlockingServer.cpp
#include "StdAfx.h"
#include "NonBlockingServer.h"

CClient::CClient()
{
	m_byteRecvData = new char[g_nMaxBufLen];
	for(int i = 0; i < 10; i++) m_byteSendData = new char[g_nMaxBufLen];
	*m_byteRecvData = '\0';
}

void CClient::Send(char *byteData)
{
	for(int i = 0; i < 10; i++)
	{
		if(!m_nSendDataSize)
		{
			strcpy(m_byteSendData[i], byteData);
			m_nSendDataSize[i] = strlen(m_byteSendData[i]);
		}
	}
}

void CClient::Send(char *byteData, int nDataSize)
{
	for(int i = 0; i < 10; i++)
	{
		if(!m_nSendDataSize && nDataSize <= g_nMaxBufLen)
		{
			memcpy(m_byteSendData[i], byteData, nDataSize);
			m_nSendDataSize[i] = nDataSize;
		}
	}
}

CNonBlockingServer::CNonBlockingServer(unsigned int nPort, unsigned int nMaxClients)
: m_nMaxClients(nMaxClients)
{
	WSAStartup(0x0202, &m_wsData);

	m_sinServer.sin_family      = AF_INET;         
    m_sinServer.sin_port      	= htons(nPort); 
    m_sinServer.sin_addr.s_addr	= htonl(INADDR_ANY);      
	m_nSinSize					= sizeof(sockaddr_in);

	m_sockServer = socket(AF_INET, SOCK_STREAM, 0);  

	bind(m_sockServer, (sockaddr *)&m_sinServer, sizeof(sockaddr));
	listen(m_sockServer, m_nMaxClients);

	m_nNumClients = 0;
}

CNonBlockingServer::~CNonBlockingServer()
{
	CClient *pClient = m_cClients->m_pPrevClient;

	while(pClient != m_cClients)
	{
		closesocket(pClient->m_sockClient);
		pClient = pClient->m_pPrevClient;
		delete pClient->m_pNextClient;
		pClient->m_pNextClient = NULL;
	}

	if(m_cClients)
	{
		closesocket(m_cClients->m_sockClient);
		delete m_cClients;
	}
}

void CNonBlockingServer:ollSockets()
{
	CClient *pClient = m_cClients;
	const timeval tvTimeout = { 0, 0 };
	int nMaxDesc = m_sockServer;

	FD_ZERO(&m_fdRecv);
	FD_ZERO(&m_fdSend);
	FD_ZERO(&m_fdError);
	FD_SET(m_sockServer, &m_fdRecv);

	for(unsigned int i = 0; i < m_nNumClients; i++)
	{
		nMaxDesc = (nMaxDesc > pClient->m_sockClient) ? nMaxDesc : pClient->m_sockClient;
		FD_SET(pClient->m_sockClient, &m_fdRecv);
		FD_SET(pClient->m_sockClient, &m_fdSend);
		FD_SET(pClient->m_sockClient, &m_fdError);
		pClient = pClient->m_pNextClient;
	}

	pClient = m_cClients;
	m_nNumSocksRdy = select(nMaxDesc, &m_fdRecv, &m_fdSend, &m_fdError, &tvTimeout);

	if(m_nNumSocksRdy == SOCKET_ERROR)
	{
		int nError = WSAGetLastError();
		char szError[5];
		sprintf(szError, "%d\n", nError);
		printf(szError);
		return;
	}

	if(FD_ISSET(m_sockServer, &m_fdRecv))
	{
		CClient *pNewClient = new CClient;

		if(m_nNumClients == 0)
			m_cClients = pNewClient;
		else if(m_nNumClients == 1)
		{
			pNewClient->m_pPrevClient = m_cClients;
			pNewClient->m_pNextClient = m_cClients;
			m_cClients->m_pNextClient = pNewClient;
			m_cClients->m_pPrevClient = pNewClient;
		}
		else
		{
			pNewClient->m_pPrevClient = m_cClients->m_pPrevClient;
			pNewClient->m_pNextClient = m_cClients;
			m_cClients->m_pPrevClient->m_pNextClient = pNewClient;
			m_cClients->m_pPrevClient = pNewClient;
		}

		pNewClient->m_sockClient = accept(m_sockServer, (sockaddr *)&pNewClient->m_sinClient, &pNewClient->m_nSinSize);
		m_nNumClients++;
		m_nNumSocksRdy--;

		pNewClient->m_pChar = new CCharacter;  //special logon code
		pNewClient->m_pChar->m_nLogonSeq = 1;  //for the mud
	}

	for(i = 0; i < m_nNumSocksRdy
	{
		if(FD_ISSET(pClient->m_sockClient, &m_fdError))
		{
			DisconnectClient(pClient);
			m_nNumSocksRdy--;
		}

		pClient = pClient->m_pNextClient;
	}
}

void CNonBlockingServer::ReceiveData()
{
	if(!m_nNumClients) return;

	CClient *pClient = m_cClients;

	for(unsigned int i = 0; i < m_nNumClients; i++)
	{
		if(FD_ISSET(pClient->m_sockClient, &m_fdRecv))
		{
			recv(pClient->m_sockClient, pClient->m_byteRecvData, g_nMaxBufLen, 0);
			m_nNumSocksRdy--;
		}

		pClient = pClient->m_pNextClient;

		if(!m_nNumSocksRdy && pClient == m_cClients || m_nNumClients == 1) return;
	}
}

void CNonBlockingServer::SendData()
{
	if(!m_nNumClients) return;

	CClient *pClient = m_cClients;

	for(unsigned int i = 0; i < m_nNumClients; i++)
	{
		if(FD_ISSET(pClient->m_sockClient, &m_fdSend))
		{
			if(pClient->m_nSendDataSize > 0)
			{
				send(pClient->m_sockClient, pClient->m_byteSendData[0], pClient->m_nSendDataSize[0], 0);
					
				for(int i = 0; i < 10; i++)
				{
					pClient->m_byteSendData[i] = pClient->m_byteSendData[i+1];
					pClient->m_nSendDataSize[i] = pClient->m_nSendDataSize[i+1];
				}
					
				m_nNumSocksRdy--;
			}

			pClient = pClient->m_pNextClient;

			if(!m_nNumSocksRdy && pClient == m_cClients || m_nNumClients == 1) return;
		}
	}
}

void CNonBlockingServer::DisconnectClient(CClient *pClient)
{
	delete pClient->m_pChar;

	closesocket(pClient->m_sockClient);
	m_nNumClients--;

	delete[] pClient->m_byteRecvData;
	for(int i = 0; i < 10; i++) delete[] pClient->m_byteSendData[i];

	pClient->m_pNextClient->m_pPrevClient = pClient->m_pPrevClient;
	pClient->m_pPrevClient->m_pNextClient = pClient->m_pNextClient;
	delete pClient;
}
 
[edited by - SyntheticHate on March 5, 2003 9:09:59 PM]

Share this post


Link to post
Share on other sites
Advertisement
Sorry, I couldn't figure out how to use the code tags to make it look better.

I also forgot to mention what it's doing wrong..
Well after a connection is accept()ed, I get the error WSAENOTSOCK from WSAGetLastError(). Hope that helps.

[edited by - SyntheticHate on March 5, 2003 9:26:07 PM]

Share this post


Link to post
Share on other sites
sounds like your listen socket isn''t valid. the following is the function i use to setup my server. i think the INADDR_ANY is causing your problems, this function retrieves the ip from the machine its running on

virtual int StartListening()
{
char szName[256];
int nRet = gethostname(szName, sizeof(szName));
if (nRet == SOCKET_ERROR)
return 0;

HOSTENT* pHost = gethostbyname(szName);
if (pHost == NULL)
return 0;

m_socketListen = socket(AF_INET, SOCK_STREAM, 0);
if (m_socketListen == INVALID_SOCKET)
return 0;

SOCKADDR_IN saServ;
saServ.sin_port = htons(YOUR_PORT_HERE);
saServ.sin_family = AF_INET;
saServ.sin_addr = *((LPIN_ADDR)*pHost->h_addr_list);
nRet = bind(m_socketListen, (LPSOCKADDR)&saServ, sizeof(SOCKADDR_IN));
if (nRet == SOCKET_ERROR)
return 0;

int nNameLen = sizeof(SOCKADDR_IN);
nRet = getsockname(m_socketListen, (LPSOCKADDR)&saServ, &nNameLen);
if (nRet == SOCKET_ERROR)
return 0;

nRet = listen(m_socketListen, SOMAXCONN);
if (nRet == SOCKET_ERROR)
return 0;
return 1;
}

Share this post


Link to post
Share on other sites

  • Advertisement