Thread View: borland.public.cppbuilder.internet.socket
9 messages
9 total messages
Started by Mike Ruskai
Tue, 04 Mar 2008 16:16
Indy10 usage
Author: Mike Ruskai
Date: Tue, 04 Mar 2008 16:16
Date: Tue, 04 Mar 2008 16:16
33 lines
2239 bytes
2239 bytes
I have an application which uses Unix-style socket calls, to which I'm attempting to add SOCKS support. Indy supposedly supports SOCKS, so I'm trying to figure out how to convert the normal socket code to the bizarre usage of Indy. I'm using BCB6 for the app in question, so I removed Indy 8, downloaded the latest Indy10 snapshot, and installed that (apparently successfully). Since the high-level protocol in use is proprietary, I'm using TIdTCPClient. I'm assigning a TIdIOHandlerStack to the IOHandler property, and a TIdSocksInfo to the TransparentProxy property of the IOHandler (though I've also tested with no proxy set - results are the same). One problem is that there's no simple functional equivalent of recv() for the IOHandler. I've tried ReadBytes() and ReadLn(), preceded by Readable() to make sure the socket can be read (that functionality is a must), just to get started on simply reading any data from the socket. I connect to a server I control, which sends data over the socket as soon as it's connected. I've confirmed with packet capture that the correct data is sent. However, while Readable() returns true, both ReadBytes() and ReadLn() read nothing at all. The Length property of the TDynByteArray sent to the former is 0, and the return string for the latter is empty. Yet calling them made the result of Readable() subsequently false. What is the correct way to simply read and write a socket?
Re: Indy10 usage
Author: Remy Lebeau (TeamB)
Date: Tue, 04 Mar 2008 17:41
Date: Tue, 04 Mar 2008 17:41
29 lines
1935 bytes
1935 bytes
"Mike Ruskai" <BUTthannydI@DONTearthlinkLIKE.netSPAM> wrote in message news:ghsqs35tipni65rjlntjpl7hgi6f1bv1g8@4ax.com... > Indy supposedly supports SOCKS, so I'm trying to figure out > how to convert the normal socket code to the bizarre usage of Indy. Simply attach a TIdSocksInfo to your TIdTCPClient. It will handle the SOCKS for you. You don't have to change anything else in your reading/writing code. > I'm assigning a TIdIOHandlerStack to the IOHandler property, and > a TIdSocksInfo to the TransparentProxy property of the IOHandler That is the way to go, yes. > One problem is that there's no simple functional equivalent of recv() > for the IOHandler. Yes, there is, which you have already discovered - Readable() and ReadBytes(). > However, while Readable() returns true, both ReadBytes() and > ReadLn() read nothing at all. Please show your actual code. Gambit
Re: Indy10 usage
Author: Mike Ruskai
Date: Tue, 04 Mar 2008 21:30
Date: Tue, 04 Mar 2008 21:30
51 lines
3135 bytes
3135 bytes
On or about Tue, 4 Mar 2008 09:41:29 -0800 did "Remy Lebeau \(TeamB\)" <no.spam@no.spam.com> dribble thusly: > >"Mike Ruskai" <BUTthannydI@DONTearthlinkLIKE.netSPAM> wrote in message >news:ghsqs35tipni65rjlntjpl7hgi6f1bv1g8@4ax.com... > >> Indy supposedly supports SOCKS, so I'm trying to figure out >> how to convert the normal socket code to the bizarre usage of Indy. > >Simply attach a TIdSocksInfo to your TIdTCPClient. It will handle the SOCKS >for you. You don't have to change anything else in your reading/writing >code. You misunderstood. I'm using normal socket code (e.g. connect(), select(), send(), recv(), etc.), not Indy. I'm adding conditional code that uses Indy instead when a SOCKS server is configured. >> One problem is that there's no simple functional equivalent of recv() >> for the IOHandler. > >Yes, there is, which you have already discovered - Readable() and >ReadBytes(). It's not equivalent at all. recv() reads data up to the buffer length specified. ReadBytes() blocks forever until the specified data length is read, or the socket is closed. In other words, ReadBytes() is useless for a normal program (i.e. one without a dedicated socket reading thread) that doesn't know exactly how many bytes are going to be sent over the socket. >> However, while Readable() returns true, both ReadBytes() and >> ReadLn() read nothing at all. > >Please show your actual code. I got that bit sort of working, by adding a delay to Readable(). It's still iffy to use. There is simply no way I can see to loop while receiving available data until the received data is deemed complete (due to the high-level protocol definition). A hack with ReadTimeout and ReadBytes() sort of works, but is so sensitive to network timing that it's worthless. As it happens, the current design uses text-only data on the control connection, so ReadLn() might work for command responses. The data connection exists only for the duration of the transfer, so ReadBytes() may actually work out. Overall, however, I have to say that Indy is a huge pain to work with for someone used to normal socket programming.
Re: Indy10 usage
Author: Remy Lebeau (TeamB)
Date: Tue, 04 Mar 2008 22:12
Date: Tue, 04 Mar 2008 22:12
45 lines
2703 bytes
2703 bytes
"Mike Ruskai" <BUTthannydI@DONTearthlinkLIKE.netSPAM> wrote in message
news:tefrs3lpnfkk0arr2qa3vospikaj3j491h@4ax.com...
> You misunderstood. I'm using normal socket code (e.g. connect(),
> select(), send(), recv(), etc.), not Indy.
You can't use TIdSocksInfo with a non-Indy connection, and there is no way
to assign your own SOCKET handle to Indy's classes without re-writing them.
> recv() reads data up to the buffer length specified.
So does ReadBytes().
> ReadBytes() blocks forever until the specified data length is read,
> or the socket is closed.
Or until a ReadTimeout elapses, if specified.
> In other words, ReadBytes() is useless for a normal program
Not really. If you want to just read what is currently available, up to but
maybe less than the desired length, then simply call the ReadFromSource()
method first and then adjust the length based on the InputBuffer's current
size. For example:
IOHandler->ReadFromSource(true, 10, false);
IOHandler->ReadBytes(buffer, min(1024, IOHandler->InputBuffer->Size));
> that doesn't know exactly how many bytes are going to be sent over the
> socket.
Most protocols are designed to offer a way of knowing that. But for those
rare cases where it simply is not, then that is why the ReadFromSource()
method and the InputBuffer property are publically accessible.
> As it happens, the current design uses text-only data on the control
> connection, so ReadLn() might work for command responses. The
> data connection exists only for the duration of the transfer, so
> ReadBytes() may actually work out.
Sounds like you are reproducing exactly what the FTP protocol already does.
Gambit
Re: Indy10 usage
Author: Mike Ruskai
Date: Wed, 05 Mar 2008 03:04
Date: Wed, 05 Mar 2008 03:04
78 lines
4253 bytes
4253 bytes
On or about Tue, 4 Mar 2008 14:12:01 -0800 did "Remy Lebeau \(TeamB\)" <no.spam@no.spam.com> dribble thusly: > >"Mike Ruskai" <BUTthannydI@DONTearthlinkLIKE.netSPAM> wrote in message >news:tefrs3lpnfkk0arr2qa3vospikaj3j491h@4ax.com... > >> You misunderstood. I'm using normal socket code (e.g. connect(), >> select(), send(), recv(), etc.), not Indy. > >You can't use TIdSocksInfo with a non-Indy connection, and there is no way >to assign your own SOCKET handle to Indy's classes without re-writing them. You misunderstood again. The above is to explain that I have normal socket code, not Indy code, which means your previous comment about assigning a TIdSockInfo and leaving the rest of the code alone didn't apply. I'm not trying to use TIdSocksInfo with normal socket calls. > >> recv() reads data up to the buffer length specified. > >So does ReadBytes(). > >> ReadBytes() blocks forever until the specified data length is read, >> or the socket is closed. > >Or until a ReadTimeout elapses, if specified. Which means you have to pick an arbitrary length of time you're willing to have the program sit doing nothing, because there's no function to read UP TO a number of bytes, from whatever's available, without blocking until that number of bytes is completely filled. >> In other words, ReadBytes() is useless for a normal program > >Not really. If you want to just read what is currently available, up to but >maybe less than the desired length, then simply call the ReadFromSource() >method first and then adjust the length based on the InputBuffer's current >size. For example: > > IOHandler->ReadFromSource(true, 10, false); > IOHandler->ReadBytes(buffer, min(1024, IOHandler->InputBuffer->Size)); > >> that doesn't know exactly how many bytes are going to be sent over the >> socket. > >Most protocols are designed to offer a way of knowing that. But for those >rare cases where it simply is not, then that is why the ReadFromSource() >method and the InputBuffer property are publically accessible. As it happens, ReadFromSource() is *not* publically accessible. It's protected. One of the big problems here is documentation. All I have to go by is the Indy 10.1.1 docs in BCB2007, since there's no hint of documentation on the Indy home page. From those docs, I can see that CheckForDataOnSource() calls ReadFromSource() internally, so is a suitable replacement for your suggestion. It seems to work as intended, provide I use a Readable() call before hand as an equivalent to select(). So thanks for that. >> As it happens, the current design uses text-only data on the control >> connection, so ReadLn() might work for command responses. The >> data connection exists only for the duration of the transfer, so >> ReadBytes() may actually work out. > >Sounds like you are reproducing exactly what the FTP protocol already does. Well, yes. Aside from the fact that none of the commands match those of FTP, the command response format is different, the data transferred is not the contents of a file. It's a proxy that sits between a desktop client and a database server. I modelled the basic design on FTP, which I've written clients for.
Re: Indy10 usage
Author: Mike Ruskai
Date: Wed, 05 Mar 2008 04:18
Date: Wed, 05 Mar 2008 04:18
24 lines
1835 bytes
1835 bytes
On or about Tue, 04 Mar 2008 22:04:47 -0500 did Mike Ruskai
<BUTthannydI@DONTearthlinkLIKE.netSPAM> dribble thusly:
>> IOHandler->[CheckForDataOnSource(10)];
>> IOHandler->ReadBytes(buffer, min(1024, IOHandler->InputBuffer->Size));
Just discovered something rather bizarre about this. ReadBytes()
throws an EIdConnClosedGracefully when the socket has been closed by
the remote after all data had been sent.
And it fails to read the data remaining in the input buffer.
So, I have to do something like this to read all data:
try
{
sock->IOHandler->ReadBytes(buf, bufsize, false);
}
catch (EIdConnClosedGracefully)
{
sock->IOHandler->InputBuffer->ExtractToBytes(buf);
}
This is not a developer-friendly library.
Re: Indy10 usage
Author: Remy Lebeau (TeamB)
Date: Wed, 05 Mar 2008 05:38
Date: Wed, 05 Mar 2008 05:38
48 lines
2727 bytes
2727 bytes
"Mike Ruskai" <BUTthannydI@DONTearthlinkLIKE.netSPAM> wrote in message
news:tu0ss39uaq8j35if50r88eflpsf5nvs431@4ax.com...
> Which means you have to pick an arbitrary length of time you're
> willing to have the program sit doing nothing, because there's no
> function to read UP TO a number of bytes, from whatever's available,
> without blocking until that number of bytes is completely filled.
Yes, there is a way, which I mentioned in my previous reply, and below.
> As it happens, ReadFromSource() is *not* publically accessible.
> It's protected.
Sorry, I meant CheckForDataOnSource() instead:
IOHandler->CheckForDataOnSource(10);
IOHandler->ReadBytes(buffer, min(1024, IOHandler->InputBuffer->Size));
> One of the big problems here is documentation. All I have to go by
> is the Indy 10.1.1 docs in BCB2007, since there's no hint of
> documentation on the Indy home page.
Then you didn't look very closely:
http://www.indyproject.org
Indy.Sockets (VCL) > Documentation
> From those docs, I can see that CheckForDataOnSource() calls
> ReadFromSource() internally, so is a suitable replacement for your
> suggestion.
Yes.
> It seems to work as intended, provide I use a Readable() call before hand
> as an equivalent to select().
You don't need to call Readable() or select() beforehand. ReadFromSource()
calls select() internally, using the timeout that you pass in.
> Well, yes. Aside from the fact that none of the commands match those
> of FTP, the command response format is different, the data transferred
> is not the contents of a file.
TIdFTP is not limited to files only. Any TStream can be used.
Gambit
Re: Indy10 usage
Author: Remy Lebeau (TeamB)
Date: Wed, 05 Mar 2008 05:46
Date: Wed, 05 Mar 2008 05:46
22 lines
1973 bytes
1973 bytes
"Mike Ruskai" <BUTthannydI@DONTearthlinkLIKE.netSPAM> wrote in message news:ch7ss31acm13alsqj2s3utjhnbusnks1a9@4ax.com... > ReadBytes() throws an EIdConnClosedGracefully when the socket > has been closed by the remote after all data had been sent. It should not be. The only time it should be raising that exception is if you are trying to read more than was actually sent. Otherwise, ReadBytes() should be returning the full requested data without raising an exception, and then the next read/write operation will detect the disconnect afterwards. Looking at the source, I do not see how that exception could be occuring. > So, I have to do something like this to read all data: No, you should not have to do that. If what you describe is actually happening (which, looking at the soure code, I don't see how it can), then it is a bug that needs fixing. Gambit
Re: Indy10 usage
Author: Mike Ruskai
Date: Wed, 05 Mar 2008 22:54
Date: Wed, 05 Mar 2008 22:54
14 lines
1667 bytes
1667 bytes
On or about Tue, 4 Mar 2008 21:38:47 -0800 did "Remy Lebeau \(TeamB\)" <no.spam@no.spam.com> dribble thusly: >> One of the big problems here is documentation. All I have to go by >> is the Indy 10.1.1 docs in BCB2007, since there's no hint of >> documentation on the Indy home page. > >Then you didn't look very closely: > > http://www.indyproject.org > Indy.Sockets (VCL) > Documentation Apparently not. Not sure how I missed that one. Maybe I was paying too much attention to the side area, since most of the other links are there.
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads