Prev: Newcomer's CAsyncSocket example: trouble connecting with other clients
Next: cannot execute C preprocessor cl.exe
From: Joseph M. Newcomer on 11 May 2010 22:14 See below... On Tue, 11 May 2010 17:44:36 -0700 (PDT), stephen park <steebu(a)gmail.com> wrote: >Hiya, > >I'm using the AsyncServer portion from Dr. Newcomer's code found here: >http://www.flounder.com/kb192570.htm > >I'm writing various clients using mfc and .net to see if I can send >messages to it. > >Since I'm completely new to socket programming, let me start by >asking, "Can you only connect to his server app by using CAsyncSocket? > >My current little bit of learning is to write a .net console app using >TcpClient to connect to it and send a message, but the message isn't >going through. The server shows a socket has been attached, but no >message gets sent, and then the socket disconnects with a message > >?.?.?.? [?] Closed **** seems odd. I've used this code to connect across the U.S. (Atlanta to various cities in California). The issue here is that I got a close notification before a connection notification. **** > >OK, yes, I realize that this is an MFC group, but I'm also >unsuccessful writing an mfc console app that uses CSocket. Well, >anyway, here's the .net version: > > > Console::WriteLine( "Sending message" ); > > TcpClient^ client = gcnew TcpClient( IP, PORT ); *** In the documentation I read, TcpClient's constructor takes no arguments. You have also not indicated what the values of the unknown variables IP and PORT are. **** > > NetworkStream ^stream = client->GetStream(); > > String^ msg = "hello there"; > array<Byte>^data = Text::Encoding::ASCII->GetBytes( msg ); > > try { > stream->Write( data, 0, data->Length ); > stream->Flush(); > } > catch( Exception ^e) { > Console::WriteLine( e->StackTrace ); > } > > > client->Close(); > > >Nothing really seems to jump out at me, but maybe someone else can see >something? > Joseph M. Newcomer [MVP] email: newcomer(a)flounder.com Web: http://www.flounder.com MVP Tips: http://www.flounder.com/mvp_tips.htm
From: Joseph M. Newcomer on 13 May 2010 18:39 It also depends on what you are using for a protocol. Note that my example requires that each "message" start with a 4-byte binary length value which is the number of bytes in the packet, and a telnet message would not conform to that protocol, so it depends on how much of my code you took to use. joe On Thu, 13 May 2010 11:53:14 -0700 (PDT), stephen park <steebu(a)gmail.com> wrote: >> I don't know what Joe's program is, but the above is correct when you >> are talking to a telnet-like like server. �I have no reason to >> question Joe's CAsyncServer, but I have not try it to see what it >> suppose to do for you. >> >> What part are you trying to make work? �What are you looking for? >> >> What I would do is begin with the basics of writing a TTY client. If >> you are just learning sockets, �you need to begin with the >> basics, which comes with "mistakes" and trial and error process. >> >> Try this TTY() function: >> >> void tty(String ^hostname, int port) >> { >> >> � � Console::WriteLine("* Connecting"); >> >> � � TcpClient^ c; >> >> � � try { >> � � � � c = �gcnew TcpClient(hostname,port); >> � � } catch(SocketException ^e) { >> � � � � Console::WriteLine(L"- Connect Error {0}",e->ErrorCode); >> � � � � Console::ReadKey(); >> � � � � return; >> � � } >> >> � � // use 100ms timeout for reader >> � � c->Client->ReceiveTimeout = 100; >> >> � � array<Byte>^ bytes = gcnew array<Byte>(1024); >> � � NetworkStream ^cio = c->GetStream(); >> >> � � while (1) { >> � � � � if (Console::KeyAvailable) { >> � � � � � � ConsoleKeyInfo^ key = Console::ReadKey(true); >> � � � � � � if (key->Key == ConsoleKey::Escape) break; >> � � � � � � try { >> � � � � � � � � cio->WriteByte(key->KeyChar); >> � � � � � � } catch( Exception ^e) { >> � � � � � � � � break; >> � � � � � � } >> � � � � } >> � � � � try { >> � � � � � � int nBytes = c->Client->Receive( bytes ); >> � � � � � � for (int i=0; i < nBytes; i++) { >> � � � � � � � � Console::Write("{0}",(wchar_t)bytes[i]); >> � � � � � � } >> � � � � } catch( SocketException ^e) { >> � � � � � � if (e->ErrorCode == 10054) { >> � � � � � � � � Console::WriteLine(L"! Disconnect"); >> � � � � � � � � break; >> � � � � � � } >> � � � � } >> � � } >> � � c->Close(); >> � � Console::WriteLine("* Closed"); >> � � Console::ReadKey(); >> >> } > > >Interesting - this code doesn't work either. Dr. Newcomer's server >says it got a connection, but when I type stuff in nothing gets sent. >I can CTRL-C and then the server says its disconnected. Sooo ... >apparently nothing is getting sent? > >I did try calling the .net versions of shutdown() and the >NetworkStream class even has a flush() function, although the doc says >that its reserved for future use. I called it anyway in my code but >still nothing got sent. > >Interestingly enough, if I try telnetting to Dr. Newcomer's server I >get the same result as the tty code above - it says its connected, but >nothing gets sent? I could type stuff in, then hit Ctrl-D, Ctrl-G, >whatever Ctrl combo that might hopefully say I'm done sending stuff, >but nothing goes ... Joseph M. Newcomer [MVP] email: newcomer(a)flounder.com Web: http://www.flounder.com MVP Tips: http://www.flounder.com/mvp_tips.htm
From: Joseph M. Newcomer on 13 May 2010 23:51
See below... On Thu, 13 May 2010 15:22:04 -0700 (PDT), stephen park <steebu(a)gmail.com> wrote: >On May 13, 2:23�pm, Hector Santos <sant9...(a)gmail.com> wrote: >> Stephen, >> >> It does work. That is why I gave you other host names and ports to try >> it. �Its a simple "Dump Terminal" client application. >> >> Not sure what exactly you are looking for? �How to make Joe's code work? > >Yeah, ok, I guess let me explain it this way. > >Assumption: The Newcomer server works. Meaning, I can send it >messages using either the Newcomer client or other client examples >I've found. And note, I'm making an assumption, so I could be wrong >and it does NOT handle incoming messages on a particular TCP port, but >all experiments seem to indicate it works just fine. **** My server works but ONLY if you conform to its protocol requirement, if you used the code exactly. This means the first 4 bytes of every message must be the length of the message text. If you are not sending this, the server, if you are using my code verbatim, will not work correctly. **** > >So, with the assumption in mind, I just want to write my own command >line client that connects to the server and sends a message like, "Hi >there!" which will display the received text. So far, using csocket, >casyncsocket (with a gui), or TcpClient, has not worked. > >Assumption: I am doing something wrong. Obviously! > >But, what is frustrating (and this is not directed at anyone here, >because you've all been very helpful) is that when I build my own >command-line socket message sender using csocket or TcpClient, it >doesn't work. And I'm either copying your code directly or looking at >other examples on MSDN or elsewhere. It just plain doesn't work, and >I'm getting very frustrated because it should! Example code on >codemasters and elsewhere I see says, "Just do this!": > >// mfc version >CSocket c; >c.Create(); >c.Connect( server, ip ); >c.Send( data ); // can't remember the exact syntax, but you get the >idea >c.Close(); **** Actually, this is not formally correct, because (a) it uses CSocket, which has serious problems and (b) it does not do a Shutdown, which means that the correct behavior is not guaranteed by the network stack. **** > >yet, when I run it, nothing gets sent. The server says it got a >connection, then the connection closed. No message was "sent". Was >it lost in the ether? Did the socket shut down without flushing the >buffer? Maybe. **** Most likely **** >But not a single example says I should do that. **** Largely because each person copies an example, which has a bug, and the bug propagates to every site that has the sample, or a derivation of it. The socket specification says that flushing is not guaranteed on a close() (or closesocket(), in WinSock). **** >How the heck would I know that I need to do that? Ok, no problem, I'll >flush the buffer by calling shutdown() or even flush(). But that >doesn't work either. So everybody's suggesting things, which again, >is very helpful and great, but nothing is working. Hence ... the >frustration. Again, not directed at anyone (except maybe me). > >So, maybe what might help would be if someone could download the >server found here: >http://www.flounder.com/kb192570.htm > >and write a simple command-line (.net or mfc) example using csocket or >TcpClient that sends a "hello" message to it. That would actually be >a good start, because if I can't get that to work, then at least I'll >know something else is up (although I've checked firewall settings, >etc.) ... **** The correct byte sequence would be the following 9 bytes '\x05' '\x00' '\x00' '\x00' 'H' 'e' 'l' 'l' 'o' because that is the protocol I specify and require, if you use my server code verbatim. If you changed it to use some other protocol, then you need to specify what protocol you are using. Every server ever written has a "protocol" that must be followed. Some of these protocols are specified in RFCs (e.g. Telnet, FTP, Ping, etc.) and some are the invention of the creator of the server; mine is the latter. **** > >And why wouldn't I use the async client found on the newcomer page? >Well, first off, I'd like to keep it really simple. I don't need to >use threads or anything, nor do I need to use a GUI. So, that kinda >rules out using casyncsocket. Surely this can be done! **** My core example was multithreaded sockets, but you can eliminate the multithreading. It was done in response to the unbelievably horrible example that Microsoft wrote, which killed at least one major project a company was doing. Such slovenliness is inexcusable (essentially, they got sockets, threading, and synchronization wrong). I built it to use a GUI interface because I wrote it to run in a pure-MFC environment and therefore could add a GUI to make it easy to demonstrate how it worked. The idea was that if you don't need multithreading, if you don't need a GUI, you should subset it, and you have to design your own protocol if you don't like mine (which is a pretty standard-vanilla protocol, by the way). joe *** > >Densely yours, and thanks everyone for the suggestions to a socket >noob ... > > Joseph M. Newcomer [MVP] email: newcomer(a)flounder.com Web: http://www.flounder.com MVP Tips: http://www.flounder.com/mvp_tips.htm |