• Advertisement
Sign in to follow this  

Winsock inside a service problem

This topic is 1653 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 got the sample from here: click

The code:





char* WebPost(char Website[], char Webpage[], char Request[], int RetLen) 
{
	// Sends an HTTP Post request with POST Data...
	// Absolutly NOT error checking, which needs fixing!

	SOCKET WebSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

	struct hostent *WebHost;
	WebHost = gethostbyname(Website);
	if (WebHost == NULL) 
	{
		if (WSAGetLastError() == WSANOTINITIALISED)
			OutputDebugString(L"Error Not Connected! line 70");
		else
			OutputDebugString(L"Error: line 72");

		Sleep(1000);
		exit(0);

	}

	SOCKADDR_IN SockAddr;
	SockAddr.sin_port	= htons(80);
	SockAddr.sin_family	= AF_INET;

	SockAddr.sin_addr.s_addr = *((unsigned long*)WebHost->h_addr);
	connect(WebSocket, (SOCKADDR*)(&SockAddr), sizeof(SockAddr));


	char PostRequest[1024];

	sprintf(PostRequest,
		"POST %s HTTP/1.1\r\n"
		"Host: %s\r\n"
		"Content-Length: %hu\r\n"
		"Content-Type: application/x-www-form-urlencoded\r\n"
		"\r\nD=%s\0",
		Webpage, Website,
		strlen(Request)+2, Request
	);

	send(WebSocket, PostRequest, strlen(PostRequest), 0);


	// Get return data 

	char* Data = new char[RetLen];
	recv(WebSocket, Data, 4, 0);

	for (;;) 
	{							// Skip HTTP headers
		Data[0] = Data[1];
		Data[1] = Data[2];
		Data[2] = Data[3];

		recv(WebSocket, &Data[3], 1, 0);

		if (Data[0] == '\r' && Data[1] == '\n'
		&&	Data[2] == '\r' && Data[3] == '\n')
			break;

	}

	int DataLen = recv(WebSocket, Data, RetLen, 0);
	Data[DataLen] = '\0';	// Return the data

	shutdown(WebSocket, 2);
	closesocket(WebSocket);
	return Data;

}







void ServStart() 
{
	WSADATA wsaData; 

	if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) 
	{
		OutputDebugString(L"error at line 138");
		exit(138);
	}


	if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) 
	{
		OutputDebugString(L"The dll do not support the Winsock versin");
		WSACleanup();
		exit(147);
	}

	// Start listening 
	ListeningSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

	if (ListeningSocket == INVALID_SOCKET) 
	{
		OutputDebugString(L"Error at socket, line 155");
		WSACleanup();
		exit(157);
	}

	ServerAddr.sin_family = AF_INET;
	ServerAddr.sin_port = htons(Port);
	ServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);

	if (bind(ListeningSocket, (SOCKADDR *)&ServerAddr, sizeof(ServerAddr)) == SOCKET_ERROR) 
	{
		OutputDebugString(L"bind failed. Error code: line 166");
		closesocket(ListeningSocket);
		WSACleanup();
		exit(169);
	}

	if (listen(ListeningSocket, 5) == SOCKET_ERROR) 
	{
		OutputDebugString(L"listen: Error listening on socket line 174");
		closesocket(ListeningSocket);
		WSACleanup();
		exit(177);
	}


// Gets your external (public) IP	< Internet
	//MyIP = WebPost("api.externalip.net", "/ip/", "", 16);			// Get my IP
	//char HostName[255];
	//hostent *HostEntry;
	//gethostname(HostName, 255);
	//HostEntry = gethostbyname(HostName);
	//MyIP = inet_ntoa(*(struct in_addr *)*HostEntry->h_addr_list);		


	char ac[80];
	if (gethostname(ac, sizeof(ac)) == SOCKET_ERROR) 
	{
		OutputDebugString(L"Error when getting local host name."); 
		exit(194);
	}

	struct hostent *phe = gethostbyname(ac);
	if (phe == 0) 
	{
		 OutputDebugString(L"Error at line 200"); 
		exit(201);
	}
	
	struct in_addr addr;
	memcpy(&addr, phe->h_addr_list[0], sizeof(struct in_addr)); // use the first ip-address
	
	MyIP = inet_ntoa(addr);

	char SendBuf[32];
	// * is used as a separator, because it's not allowed in the hostname. 
	//So it won't interfere with it. 
	sprintf(SendBuf, "%hhu|%s*%s", cAddIP, MyIP, ac);	// Send the server the IP and host name
	WebPost(WEBSITE, WEBPAGE, SendBuf, 0);

	OutputDebugString(L"listening for connections...\n\n");

}

void ShutDown() 			// Shut down the server (tells the web server I am offline)
{
	char SendBuf[32];		// Remove my IP from the list of online servers...
	char ac[80];
	if (gethostname(ac, sizeof(ac)) == SOCKET_ERROR) 
	{
		printf("Error when getting local host name: ", WSAGetLastError()); 
		exit(226);
	}
	sprintf(SendBuf, "%hhu|%s*%s", cRemIP, MyIP,ac);
	WebPost(WEBSITE, WEBPAGE, SendBuf, 0);

	printf("Successful shutdown\n");
	Sleep(1000);

	WSACleanup();

}








void CSampleService::ServiceWorkerThread(void)
{
	ServStart();
	

	
    // Periodically check if the service is stopping.
	
    while (!m_fStopping)
	{
    

	SOCKADDR_IN SenderInfo;
	SOCKET NewConnection;

	int ByteReceived, nlen;
	char recvbuff[1024];
		// Main program loop
		NewConnection = SOCKET_ERROR;
		if(NewConnection == SOCKET_ERROR) 
		{
		
			NewConnection = accept(ListeningSocket, NULL, NULL);	// this is a blocking function
			OutputDebugString(L"New client got connected, ready to receive and send data...\n\n");
			ByteReceived = recv(NewConnection, recvbuff, sizeof(recvbuff), 0);

			if (ByteReceived > 0) 
			{
				getsockname(ListeningSocket, (SOCKADDR *)&ServerAddr, (int *)sizeof(ServerAddr));

				memset(&SenderInfo, 0, sizeof(SenderInfo));
				nlen = sizeof(SenderInfo);

				getpeername(NewConnection, (SOCKADDR *)&SenderInfo, &nlen);	
			}

		}
		if (shutdown(NewConnection, 2) != 0)
			OutputDebugString(L"Line 355");
		else
			OutputDebugString(L"shutdown is working...\n");

		

	
	}

    // Signal the stopped event.
    SetEvent(m_hStoppedEvent);
}

As you can see,it's the code form a simple server.But,when I try to connect to it,nothing.If I just run it as a console app,it works fine.

What's the problem?

Edited by noatom

Share this post


Link to post
Share on other sites
Advertisement

printf isn't going to work in a service. Have you set breakpoints on all the exit(0) calls/failures?

 

(Also, exit(0) means "everything is ok", same as returning 0 from main(). You should probably exit with a non-zero error code?).

Edited by Paradigm Shifter

Share this post


Link to post
Share on other sites

Neither will work anything GUI related towards the user. Services per default are not supposed to interact with the Desktop.

 

However it's possible to enable interaction manually (in the Service Manager). Not recommended though. Write a log file somewhere or use the Event Manager..

Share this post


Link to post
Share on other sites

So,printfs and exit codes....I'm pretty sure they're not affecting the code,they're just leftovers from the copy-paste.

 

And this is just winsock,it is not intended to react with the desktop.I'm gonna create a log file..

Share this post


Link to post
Share on other sites

I updated the code in the first post.

 

So I changed the printfs to outputdebugstrings and the exit codes to the number of the line in visual studio,I also removed the messageboxes,but all I get in visual studio is:

'CppWindowsService.exe': Loaded 'C:\test2\CppWindowsService.exe', Symbols loaded.
'CppWindowsService.exe': Loaded 'C:\Windows\System32\ntdll.dll', Cannot find or open the PDB file
'CppWindowsService.exe': Loaded 'C:\Windows\System32\kernel32.dll', Cannot find or open the PDB file
'CppWindowsService.exe': Loaded 'C:\Windows\System32\KernelBase.dll', Cannot find or open the PDB file
'CppWindowsService.exe': Loaded 'C:\Windows\System32\advapi32.dll', Cannot find or open the PDB file
'CppWindowsService.exe': Loaded 'C:\Windows\System32\msvcrt.dll', Cannot find or open the PDB file
'CppWindowsService.exe': Loaded 'C:\Windows\System32\sechost.dll', Cannot find or open the PDB file
'CppWindowsService.exe': Loaded 'C:\Windows\System32\rpcrt4.dll', Cannot find or open the PDB file
'CppWindowsService.exe': Loaded 'C:\Windows\System32\msvcr100d.dll', Symbols loaded.
'CppWindowsService.exe': Loaded 'C:\Windows\System32\msvcp100d.dll', Symbols loaded.
'CppWindowsService.exe': Loaded 'C:\Windows\System32\ws2_32.dll', Cannot find or open the PDB file
'CppWindowsService.exe': Loaded 'C:\Windows\System32\nsi.dll', Cannot find or open the PDB file
'CppWindowsService.exe': Loaded 'C:\Windows\System32\mswsock.dll', Cannot find or open the PDB file
'CppWindowsService.exe': Loaded 'C:\Windows\System32\user32.dll', Cannot find or open the PDB file
'CppWindowsService.exe': Loaded 'C:\Windows\System32\gdi32.dll', Cannot find or open the PDB file
'CppWindowsService.exe': Loaded 'C:\Windows\System32\lpk.dll', Cannot find or open the PDB file
'CppWindowsService.exe': Loaded 'C:\Windows\System32\usp10.dll', Cannot find or open the PDB file
'CppWindowsService.exe': Loaded 'C:\Windows\System32\imm32.dll', Cannot find or open the PDB file
'CppWindowsService.exe': Loaded 'C:\Windows\System32\msctf.dll', Cannot find or open the PDB file
'CppWindowsService.exe': Loaded 'C:\Windows\System32\WSHTCPIP.DLL', Cannot find or open the PDB file
'CppWindowsService.exe': Loaded 'C:\Windows\System32\nlaapi.dll', Cannot find or open the PDB file
'CppWindowsService.exe': Loaded 'C:\Windows\System32\NapiNSP.dll', Cannot find or open the PDB file
'CppWindowsService.exe': Loaded 'C:\Windows\System32\pnrpnsp.dll', Cannot find or open the PDB file
'CppWindowsService.exe': Loaded 'C:\Windows\System32\dnsapi.dll', Cannot find or open the PDB file
'CppWindowsService.exe': Loaded 'C:\Windows\System32\winrnr.dll', Cannot find or open the PDB file
'CppWindowsService.exe': Loaded 'C:\Windows\System32\IPHLPAPI.DLL', Cannot find or open the PDB file
'CppWindowsService.exe': Loaded 'C:\Windows\System32\winnsi.dll', Cannot find or open the PDB file
'CppWindowsService.exe': Loaded 'C:\Windows\System32\FWPUCLNT.DLL', Cannot find or open the PDB file
'CppWindowsService.exe': Loaded 'C:\Windows\System32\rasadhlp.dll', Cannot find or open the PDB file
The thread 'Win32 Thread' (0x68c) has exited with code 0 (0x0).

I debugged the service like this: http://msdn.microsoft.com/en-us/library/7a50syb3.aspx

 

Some help?

Edited by noatom

Share this post


Link to post
Share on other sites

I checked with the services in the services manager,it does not stop,however it throws these messages:

The thread 'Win32 Thread' (0x68c) has exited with code 0 (0x0).

 

with different hexadecimal codes like every 2 minutes.

Share this post


Link to post
Share on other sites

That's normal as well... threads get spawned and exit quite a lot.

 

Are you sure OutputDebugString is working? It looks like you don't get any output at all from your program. Output something as soon as your program starts (dunno what the entry point for a service is). You are running the service through the debugger, right? (Presumably, since you see some output).

 

If you do see output, you want to output stuff that succeeds as well and put some output throughout the program so you can see what it is doing.

Share this post


Link to post
Share on other sites

Starting with Vista services run in "session 0", while normal programs run in "session 1". It's not so easy to capture OutputDebugString output with VS now.

 

You could use DebugView (http://technet.microsoft.com/en-us/sysinternals/bb896647.aspx) which has an option to capture global ODS calls (named something like global win32).

 

Or as said, use a log file or the event system ;)

Share this post


Link to post
Share on other sites

Outputdebug does NOT work. I must have like 20 of them in my service and I never get to see one in visual studio.I'll try what endurion said.

 

Not sure if debugview doesn't work or I'm not using it the right way...i see nothing in the list

Edited by noatom

Share this post


Link to post
Share on other sites

I'd go for a logfile then. C:\out.txt or something like that.

 

Do breakpoints work? You probably want to narrow the problem down a bit before you start stepping through code though.

Share this post


Link to post
Share on other sites
void CSampleService::ServiceWorkerThread(void)
{
	ServStart();
	

	
    // Periodically check if the service is stopping.
	FILE* pFile = fopen("logFile.txt", "a");
    fprintf(pFile, "%s\n","In worker function");
    while (!m_fStopping)
	{
    

	SOCKADDR_IN SenderInfo;
	SOCKET NewConnection;

	int ClientLen = sizeof(SOCKADDR_IN);
	SOCKADDR_IN ClientAddr;

	int ByteReceived, nlen;
	char recvbuff[1024];
		// Main program loop
		NewConnection = SOCKET_ERROR;
		if(NewConnection == SOCKET_ERROR) 
		{
		
			//NewConnection = accept(ListeningSocket, NULL, NULL);	// this is a blocking function
			NewConnection = accept(ListeningSocket,(SOCKADDR*)&ClientAddr, &ClientLen);
			OutputDebugString(L"New client got connected, ready to receive and send data...\n\n");
			ByteReceived = recv(NewConnection, recvbuff, sizeof(recvbuff), 0);

			if (ByteReceived > 0) 
			{
				fprintf(pFile, "%s\n","Received bytes!");
				getsockname(ListeningSocket, (SOCKADDR *)&ServerAddr, (int *)sizeof(ServerAddr));

				memset(&SenderInfo, 0, sizeof(SenderInfo));
				nlen = sizeof(SenderInfo);

				getpeername(NewConnection, (SOCKADDR *)&SenderInfo, &nlen);	
			}

		}
		if (shutdown(NewConnection, 2) != 0)
			OutputDebugString(L"Line 355");
		else
			OutputDebugString(L"shutdown is working...\n");

		

	
	}
	fclose(pFile);
    // Signal the stopped event.
    SetEvent(m_hStoppedEvent);
}

So,see that ServStart() call at the begining,it turns out it calls that function(saw it on a logfile),but after it gets out of it,it doesn't to anything.I mean when it gets out it should post some of those lines of text,but it doesn't.

 

Why would the call to StartServer do fine,and after that "nothing happens" ?

Share this post


Link to post
Share on other sites

Print more stuff to the file. You are still using OutputDebugString as well...

 

Does accept() ever return? You can probably just put a breakpoint on the OutputDebugString following to see if it does.

 

When tracing I usually log

 

+functionname()

 

at the start of each function and

 

-functionname()

 

everywhere it returns/exits, along with other information, especially before and after calls to blocking functions...

Share this post


Link to post
Share on other sites

For one, m_fStopping might be true (or worse, uninitialized).

You really need to cover everything from the start downwards to see where the CPU is branching into and where not.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement