Page 1 of 1

Linux: socket sends only one byte

Posted: Sun May 06, 2007 6:37 pm
by DFYX
I've written a small IRC Client with wxWidgets. It runs fine on Windows XP and there were no problems on Linux in the past, but when I tried if the latest version runs on Linux, something strange happened. For every Write() only one byte is sent. At least that's what Wireshark tells me. I use the following code:

Code: Select all

void wxIRC::SendRaw(wxString string)
{
	if(socket->IsConnected())
	{
		if(string.Right(1) != wxT("\n"))
  		{
			string.Append(wxT("\n"));
		}
		const char *buf = (const char*) string.c_str();
  		unsigned int len = strlen(buf);
  		
  		socket->Write((const void*) buf, len);
	}
}
Don't know what the problem is. It still works on Windows, len gets the correct value and it can't be a problem with my computer because two friends of mine reported the same problem. As far as I can remember, I haven't even touched that function for weeks.

You can get the complete source from https://wxirc.svn.sourceforge.net/svnroot/wxirc/trunk

Here's what Wireshark tells me:

Code: Select all

Request: U
Request: N
[A little later]
Response: ERROR :Closing Link: [***.***.***.***] (Ping timeout)
(Replaced my IP with *)

Posted: Mon May 07, 2007 6:25 am
by clyde729
The link to your sources doesn't work for me. Anyhow, please show us the socket-flags you set.

I worked with sockets too and in a single thread app you can use NO_WAIT for reading and writing under windows, but you will have to use WAIT_ALL for writing (and optional NO_WAIT for reading). This is the way it works for me. Try to play around with it.

Posted: Mon May 07, 2007 9:35 am
by DFYX
If the link doesn't work, try http://wxirc.svn.sourceforge.net/svnroot/wxirc/trunk/ Sourceforge can be quite strange :wink:

Your tip sounds quite good, but using wxSOCKET_WAITALL in the constructor didn't help.

Posted: Mon May 07, 2007 9:36 am
by lowjoel

Code: Select all

   97 void wxIRC::SendRaw(wxString string)
   98 {
   99 	if(socket->IsConnected())
  100 	{
  101 		if(string.Right(1) != wxT("\n"))
  102   		{
  103 			string.Append(wxT("\n"));
  104 		}
  105 		const char *buf = (const char*) string.c_str();
  106   		unsigned int len = strlen(buf);
  107 
  108   		socket->Write((const void*) buf, len);
  109 	}
  110 }
That's very dangerous code IMHO. We're using C++, so why should be still be using c-style casts? I'm suspecting that your c_str call is returning a wchar_t*, and in your C-style cast it is casted to const char* without warning or error. When you send it to Wireshark they may not completely see that it is encoded in UCS-2 and just show your 1 byte of information.

Also PLEASE practice some debugging techniques. If you're writing such a program I believe you have been programing for a while. So, try using GDB to see the value of buf to see if it is done correctly and stuff like that.

Oh, one more problem. If you are using CVS HEAD, c_str no longer returns const char* or const wchar_t*, its now wxCStrData. You may need to cast it to const char* to get the value out. Here is the next danger of using C-style casts, if it is an integer you cast it to be an address without knowing. In your call to socket->Write wxCStrData may have contained an implicit conversion function which may not work for the cast to const void*.

Joel

Posted: Mon May 21, 2007 10:27 am
by DFYX
Phew... thanks for your answers. Didn't have any time in the last few days so I couldn't answer.

@lowjoel:
Well, I guess you're right. I found some similar code somewhere else and just changed a few things. I didn't think much about casts, since it worked on my windows machine.

So if this is the real problem, using wxWX2MBbuf and mb_str(wxConvUTF8); (as in Calindora) would help, wouldn't it? I tried it and well... it didn't work. Any other ideas?

EDIT:
OK, now it works. Don't know why, but it does. I haven't changed anything. I still have some problems with receiving, but I guess, I'll find a solution on my own.