When I connect to 80 port, plain text web site using TIdTCPClient component, all works fine, data is received without a problem, but, when I connect to 443 port, SSL web site, data not always came.
Maybe something with my receive data block ? Need advice.
while not Terminated do
begin
SetLength(data, 0);
ws.IOHandler.ReadBytes(data, -1);
if Length(data) = 0 then
break;
// processing_my(data);
end;
Thanks
Opening the connection to an other port to have it secure is not enough. To connect to anything SSL, you'll need an IOHandler that supports it, such as TIdSSLIOHandlerSocketOpenSSL
Related
I have a TCP connection (proxy) that connects through socks4-5 and sends http / https / DNS traffic through it.
I need something to share, something to http / https etc. went through tcp connection 1 and dns resolve through tcp connection 2
I tried to create IdTCPServer1 (But I'm not sure on the right track), it connects but nothing sends him.
In addition, he hangs on until ReadLn it will not be recorded data, and it is not permissible.
procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
var str_str:String;
begin
str_str:=AContext.Connection.Socket.ReadLn();
if(str_str<>'') then Memo1.Lines.Add('#TCP_SERVER: EXECUTE: '+str_str);
You need to handle (implement) the socks4/5 server side protocol (See http://tools.ietf.org/rfc/rfc1928.txt). The in the request, you can intercept to port number to see if it is http, dns or whatever. Then you forward the connection according to it.
I've written a small application using delphi to update my twitter status.
I use Indy 10 and OpenSSL and everything works fine, which means that i can both authenticate my app and update my status.
The thing is that if i use a program like "http analyzer" i can see the request's headers and so i can see sensitive information like the consumer_key.
Is that normal or is it a sign that i have not set properly the iohandler (TIdSSLIOHandlerSocketOpenSSL)?
mSslIoHandler.SSLOptions.Method := sslvSSLv3;
mSslIoHandler.SSLOptions.Mode := sslmBoth;
mSslIoHandler.SSLOptions.VerifyMode := [];
mSslIoHandler.SSLOptions.VerifyDepth := 0;
By providing their own SSL certificates, HTTP analyzers are able to monitor the HTTP traffic as if it was unencrypted. I guess you have to set the analyzer IP address and port as proxy only, and leave the destination server address and port unchanged in the client. Then the analyzer will be able to decrypt your client data with its own key, and forwards it to the destination server. (This is the same way a 'man in the middle'-attack would work)
So yes, it is normall with this type of HTTP analyzers (such as Fiddler)
I have a datasnap server with a vcl forms client. From the client, how can I handle if the server has been say shutdown and restarted with existing client connections? This scenario raises a 10053 EIdSocketError exception.
To replicate, I run up both Server and Client, make a call to the server (I use methods exposed via the DataSnap proxy generator) which succeeeds. I then shut down the server (eg Close the application) and restart it. I then attempt to make a call to the server again.
eg:
CLIENT call
sm := TsvrPolicySearchClient.Create(datClientDB.SQLConnection1.DBXConnection);
try
ds := sm.SearchPolicyByPolicy(40, WCRef, '', 3);
dspPolicyGroup.DataSet := ds;
if cdsPolicyGroup.Active then
cdsPolicyGroup.Refresh
else
cdsPolicyGroup.Open;
finally
sm.Free;
end;
dspPolicyGroup is a TDataSetProvider and cdsPolicyGroup is a TClientDataSet (I just use it locally to "store" my TDataSet result).
SERVER
function TsvrPolicySearch.SearchPolicyByPolicy(AClientId: Integer; WCRefNum, ClientRef: string; SearchMethod: Integer): TDataSet;
begin
spPolicyByWCRef.Close;
spPolicyByWCRef.ParamByName('p_client').AsInteger := AClientId;
spPolicyByWCRef.ParamByName('p_search_method').AsInteger := SearchMethod;
spPolicyByWCRef.ParamByName('p_wc_refno').AsString := WCRefNum;
spPolicyByWCRef.Open;
Result := spPolicyByWCRef;
end;
I would think this is regularly encountered by people seeing that it's quite easy to replicate. Should I place a "Test Connection" call or something first (such as a method TestConnection) before each call to check for EIdSocketError (and equivalent) and handle? Or is it more a design flaw perhaps?
Thanks
My scenario:
Client application connect to DataSnap Server (TCP/IP, remote server)
Client request a DataSet (using DataSnap server methods). TClientDataSet
Client downloaded dataset
Server shutdown (taskkill, close application no matters)
Client request a DataSet againt (ehhrrr Socket Error)
Solution:
On client I catch exception (AppEvents.OnException)
Recognize that is Socket error from connection to DataSnap server
I show dialog window with information that connection is lost. User can click "RETRY" - if so,
Free and re-create DataSnap client module and initialize connection
Try to request dataset (special dataset for connection test) if application catch exception entire process works from the beginning.
After this operation my Client re-connect to DataSnap server and can request dataset using new TCP/IP connection. Of course user can close dialog, but then application is turn off.
I think this can help you. I tried many others solutions but this proved to be the best. Moreover algorithm also supports the loss of connection with the client's fault.
The easiest workaround for this problem is to change the TDSServerClass LifeCycle attribute to Invocation.
This will cause you to have a stateless server, and the server will create a new session per request. But, you will be able to close and reconnect the server without interrupting the clients connection.
I want to use UDP Socket to simply send an audio stream. My problem is that i can't get it working i thought it would be simpler then using TCP IP.
What i did i droped a UDPSocket component on my form and for the server part i used this code
with udpServer do
begin
LocalHost := '127.0.0.1';
LocalPort := '5002';
Open();
Active := True;
end;
For the client application this :
with udpClient do
begin
RemoteHost := '192.0.168.100'; //my local address
RemotePort := '5002';
Open();
Active := True;
end;
The problem is i am not receving anything. What i am doing wrong i don't have any third-party software that can block the connection.
I didn't find any suitable example for using this component any source of inspiration will be greatly appreciated.
You have the server and the client connect on the same IP.
Usually if you set the server application IP address to 0.0.0.0 it will bind to any available IP address on the given port, including 127.0.0.1.
Then the client must connect to one of the bound IPs. Instead, you had the server listening on 127.0.0.1 and the client connect to 192.0.168.100.
Don't be fooled by the "LocalHost" property name. "Local" here just mean you have to set a "local" IP, an IP assigned to the local machine, not a "remote" (of another machine) one, while the client of course will connect to a "remote" IP, that of the server.
127.0.0.1 is a good choice if and only if you want your server to be available only to local application, because that IP scope is limited to the same machine. If you want to make it available outside the machine, you have to bind it to a valid IP.
Whatever issue you have, tools like Wireshark or Microsoft Network Monitor are very useful to understand what's going on.
You are binding the server to 127.0.0.1, so it will only accept clients that connect to 127.0.0.1 specifically. Your client is connecting to 192.0.168.100 (perhaps you meant 192.168.0.100?) instead.
You need to bind the server to the IP(s) that clients are actually connecting to, or else bind it to 0.0.0.0 to accept connections on any local IP.
Even though UDP is connectionless, this same rule applies to both UDP and TCP, as it applies to the lower level IP routing layer that they both share.
How can Indy's TIdTCPClient and TIdTCPServer be used in the following scenario:
Client ---------- initate connection -----------> Server
...
Client <---------------command------------------- Server
Client ----------------response-----------------> Server
...
Client <---------------command------------------- Server
Client ----------------response-----------------> Server
The client initiates the connection, but acts as a "server" (waiting for commands and executing them).
The OnExecute approach of TIdTCPServer does not work well in this case (at least I am not getting it to work well). How could I do this?
I hope the question is clear enough.
There is nothing preventing you from doing this with Indy's TIdTCPServer component.
A TIdTCPServer only sets up the connection. You'll need to implement the rest. So the sequence of the actual sending and receiving can be whatever you want.
Put this code in your TIdTCPServer component's OnExecute event:
var
sName: String;
begin
// Send command to client immediately after connection
AContext.Connection.Socket.WriteLn('What is your name?');
// Receive response from client
sName := AContext.Connection.Socket.ReadLn;
// Send a response to the client
AContext.Connection.Socket.WriteLn('Hello, ' + sName + '.');
AContext.Connection.Socket.WriteLn('Would you like to play a game?');
// We're done with our session
AContext.Connection.Disconnect;
end;
Here's how you can setup the TIdTCPServer really simply:
IdTCPServer1.Bindings.Clear;
IdTCPServer1.Bindings.Add.SetBinding('127.0.0.1', 8080);
IdTCPServer1.Active := True;
This tells the server to listen on the loopback address only, at port 8080. This prevents anyone outside of your computer from connecting to it.
Then, to connect your client, you can go to a Windows command prompt and type the following:
telnet 127.0.0.1 8080
Here's the output:
What is your name?
Marcus
Hello, Marcus.
Would you like to play a game?
Connection to host lost.
Don't have telnet? Here's how to install telnet client on Vista and 7.
Or with a TIdTCP Client, you can do this:
var
sPrompt: String;
sResponse: String;
begin
// Set port to connect to
IdTCPClient1.Port := 8080;
// Set host to connect to
IdTCPClient1.Host := '127.0.0.1';
// Now actually connect
IdTCPClient1.Connect;
// Read the prompt text from the server
sPrompt := IdTCPClient1.Socket.ReadLn;
// Show it to the user and ask the user to respond
sResponse := InputBox('Prompt', sPrompt, '');
// Send user's response back to server
IdTCPClient1.Socket.WriteLn(sResponse);
// Show the user the server's final message
ShowMessage(IdTCPClient1.Socket.AllData);
end;
An important thing to note here is that the ReadLn statements wait until there is data. That's the magic behind it all.
If your commands are textual in nature, then have a look at the TIdCmdTCPClient component, it is specifically designed for situations when the server is sending commands instead of the client. The server can use TIdContext.Connection.IOHandler.WriteLn() or TIdContext.Connection.IOHandler.SendCmd() to send the commands.
When the client connects to the server, the server has an OnConnect event with an AContext: TIdContext parameter.
A property of this is AContext.Connection, which you can store outside of that event (say, in an Array). If you pair it with the IP or better yet a generated Session ID, then reference that Connection by that criteria, you can then have the server send adhoc commands or messages to the client.
Hope this helps!
normally the client and the server side have a thread that is reading incoming telegrams, and sending pending telegrams...but this kind of protocols (send/receive, when and what) depend of the application.
A very good starting point how the client side can be implemented using a thread, listening for messages from the server, is the Indy Telnet client component (TIdTelnet in the Protocols folder).
The Indy telnet client connects to the telnet server and uses only one socket to write and read data. Reading happens in a listener thread.
This design can easily be adapted to build distributed messaging software like chat etc., and also shows how easy the protocol can be decoupled from the network layer using blocking sockets.
With Indy this is not possible by design:
Indy supports only Client-initiated communication, what means the server can only send a response to requests by the client.
The easiest way (but not the smartest) to get what you want is to use a pull-process. Controlled by a timer the clients ask the server if there is a new command. Of course this will cause a lot of traffic-overhead and depending on your pull-intervall there is a delay.
Alternatively you could use another library like ICS (http://www.overbyte.be/eng/products/ics.html)