WinSock - program dziala na win7, na xp sie wysypuje...

0

Witam! Na poczatek wrzucam kod:

SERWER:

struct SPakiet
{
	int cmd;
	int dlpakietu;
};


class CSerwer
{
private:
	WSADATA	wsd;
	int conn_port;
	SOCKET sListen;
	int Transfer_Error;
	std::vector<SOCKET> SockTab;
	DWORD ListenThread();
	DWORD SocketThread();
	int sendall( int s, char * buf, int len );
		
public:
	
	
	static DWORD WINAPI StartListenThread(CSerwer* srv) { return srv->ListenThread(); };
	static DWORD WINAPI StartSocketThread(CSerwer* srv) { return srv->SocketThread(); };

	CSerwer():Transfer_Error(-1) {SockTab.push_back(*(new SOCKET));};
	~CSerwer(); 
	bool Init(int port);
	bool SendCMD(int SockIndex, int iCMD, char* cmd);

};
...
...

int CSerwer::sendall( int s, char * buf, int len )
{
    int total = 0; 
    int bytesleft = len; 
    int n;
   
    while( total < len ) {
        n = send( s, buf + total, bytesleft, 0 );
        if( n == - 1 ) { break; }
        total += n;
        bytesleft -= n;
    }
    
    return total<len?- 1: 1;
}


bool CSerwer::Init(int port)
{
	conn_port=port;
    sockaddr_in	local;
	

    if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
    {
		#ifdef DEBUG
		logger.LogError("Blad przy starcie WSAStartup. kod bledu: %d", WSAGetLastError());
		#endif

        return 0;
    }

    sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
    if (sListen == SOCKET_ERROR)
    {
		#ifdef DEBUG
		logger.LogError("Blad przy tworzeniu socketu. kod bledu: %d", WSAGetLastError());
		#endif
        return 0;
    }

	local.sin_addr.s_addr = htonl(INADDR_ANY);
	local.sin_family = AF_INET;
	local.sin_port = htons((u_short)conn_port);

    if (bind(sListen, (sockaddr *)&local, sizeof(local)) == SOCKET_ERROR)
    {
		#ifdef DEBUG
		logger.LogError("Blad przy ustawianiu socketu. kod bledu: %d", WSAGetLastError());
		#endif
        return 0;
    }
	
	CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CSerwer::StartListenThread, this, 0, NULL);
   
	return true;
}

DWORD CSerwer::ListenThread()
{


	sockaddr_in client;
	listen(sListen, SOMAXCONN);
	int iAddrSize = sizeof(client);
	

	
	while(1)
	{
		SockTab[SockTab.size()-1] = accept(sListen, (sockaddr *)&client, &iAddrSize);
		if (SockTab[SockTab.size()-1] == INVALID_SOCKET)
		{
			#ifdef DEBUG
			logger.LogInfo("Nie mozna zaakceptowac uzytkownika. kod bledu: %d ", WSAGetLastError());
			#endif
			continue;
		}

		#ifdef DEBUG
		logger.LogInfo("Zaakceptowano polaczenie z uzytkownikiem");
		#endif

		SockTab.push_back(*(new SOCKET));

		CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CSerwer::StartSocketThread, this, 0, NULL);

	}

	return 1;
};


DWORD CSerwer::SocketThread()
{
	int SockIndex=SockTab.size()-2;
	SPakiet pakiet;

	//Sprawdzanie poprawnosci klienta --------------------------------------------------------------------------------------
	if(recv(SockTab[SockIndex], reinterpret_cast<char*>(&pakiet), sizeof(pakiet), MSG_WAITALL)<=0 || pakiet.cmd!=WELCOME)
	{
		#ifdef DEBUG
		logger.LogError("Odrzucono polaczenie z klientem(brak odpowiedzi WELCOME). kod bledu: %d", WSAGetLastError());
		#endif
		return 1;
	}

//  PO wywolaniu sendall na kliencie pokazuje sie error 10045 i program wisi//
	if(!sendall(SockTab[0], reinterpret_cast<char*>(&pakiet), sizeof(pakiet)) ) 
	{
		
		#ifdef DEBUG
		logger.LogInfo("Blad! Czesc pakietu nie zostala wyslana!! kod bledu: ", WSAGetLastError());
		#endif
	}

	//Sprawdzanie poprawnosci klienta ---------------------------------------------------------------------------------------
 //  PO wywolaniu sendall na kliencie pokazuje sie error 10045 i program wisi//
	
	while(1)
	{
		
		if(recv(SockTab[SockIndex], reinterpret_cast<char*>(&pakiet), sizeof(pakiet), MSG_WAITALL)<=0)
		{

             ...
         }

 

KLIENT

 

class CServer
{
private:
	SOCKET sClient;
	std::string CServer::exec_CMD(char* cmd); 
	WSADATA wsd;
public:
	bool init(char adrIP[128], int port);
	void CMD_Proc();
	~CServer();
};


bool CServer::init(char adrIP[128], int port)
{
	sockaddr_in server;
    hostent    *host = NULL;
	
	

  
    if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
    {
		#ifdef DEBUG
		logger.LogInfo("Blad przy WSAStartup. kod bledu: %d", WSAGetLastError());
		#endif
        return false;
    }

    sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sClient == INVALID_SOCKET)
    {
		#ifdef DEBUG
		logger.LogError("Blad przy tworzeniu socketu. kod bledu: %d", WSAGetLastError());
		#endif
        return false;
    }

    server.sin_family = AF_INET;
    server.sin_port = htons((u_short)port);
    server.sin_addr.s_addr = inet_addr(adrIP);

   
    if (server.sin_addr.s_addr == INADDR_NONE)
    {
        host = gethostbyname(adrIP);
        if (host == NULL)
        {
			#ifdef DEBUG
			logger.LogError("Blad przy przeksztalcaniu adresu na IP. kod bledu: %d", WSAGetLastError());
			#endif
            return false;
        }
        CopyMemory(&server.sin_addr, host->h_addr_list[0], host->h_length);
    }

    if (connect(sClient, (sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
    {
		#ifdef DEBUG
		logger.LogError("Blad przy probie polaczenia. kod bledu: %d", WSAGetLastError());
		#endif
        return false;
    }
	
	SPakiet pak;

	pak.cmd=WELCOME;
	sendall(sClient, reinterpret_cast<char*>(&pak), sizeof(pak));
	

	pak.cmd=0;
	recv(sClient, reinterpret_cast<char*>(&pak), sizeof(pak), 0);



	if(pak.cmd!=WELCOME)
	return false;

	#ifdef DEBUG
	logger.LogInfo("Polaczono!");
	#endif
	


	return true;
}


void CServer::CMD_Proc()
{
	SPakiet pakiet;
	while(1)
	{
               //TUTAJ ZRYWA POLACZENIE, przynajmniej tak wychodzi z tego warunku//
		if(recv(sClient, reinterpret_cast<char*>(&pakiet), sizeof(pakiet), MSG_WAITALL)<=0)
		{
			#ifdef DEBUG
			logger.LogError("Zerwano polaczenie z klientem. kod bledu: %d", WSAGetLastError());
			#endif

			return;
		}
		
		switch(pakiet.cmd)

                 ...
                 ...
}

Kupa kodu, ale chyba bez niego nikt nie bylby w stanie mi pomoc. Problem polega na tym ze program dziala w 100% poprawnie na windows 7 a na win xp zrywa polaczenie - recv zwraca -1 w kliencie w CMD_Proc(), error 10045. Rece mi opadaja bo nie mialem jeszcze takiej sytuacji, patrzylem czy ten error 10045 nie pochodzi z poprzednich wywolan funkcji i na pewno tak nie jest, patrzylem czy gdzies przypadkiem nie modyfikuje socketu klienta - tez wykluczone. Moze zle inicjalizuje WinSock? Dodam, ze tam gdzie recv() zwraca -1 u klienta, w serwerze funkcja sendall mowi ze caly pakiet zostal wyslany.

Reasumujac, nie wiem czy klient czy serwer(ale raczej klient, skoro serwer z klientem na win 7 dziala ok) zrywa polaczenie zaraz po wyjsciu z Init() - po sprawdzeniu poprawnosci klienta czyli wyslaniu i odebraniu WELCOME.
Prosze zeby ktos ogarniety w WinSock rzucil na to okiem, bo po paru godzinach wysiadam. Dzieki z gory :)

0

Flaga MSG_WAITALL jest obsługiwana od Windowsa 2003 wzwyż.

0

Ehh ja jestem jakis slepy czy tu http://msdn.microsoft.com/en-us/library/windows/desktop/ms740121%28v=vs.85%29.aspx nawet o tym nie wspomnieli? Skad mam to wiedziec?

Dzieki za odpowiedz, zaoszczedziles mi duuuzo czasu :). Jutro poprawie i napisze czy juz jest ok.

edit
Wszystko dziala, dziekuje za pomoc! :))

1 użytkowników online, w tym zalogowanych: 0, gości: 1