Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations MikeeOK on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

TCPClient.SendLn problem

Status
Not open for further replies.

momtchil

Programmer
Mar 19, 2006
4
BG
I noticed that the TCPclient (supplied by Indy) sends data from a random port of my computer. Is there a way I can define this port? Or at least know which one it is..

thanks in advance :)
 
The BoundPort property family?

buho (A).
 
I can't think of a reason why you'd want to set this. Having the port be random is normal behaviour for client programs. It's only if your program is accepting connections (ie with a TCPServer component in indy), that you need to define a specific port.

Because there may be hundreds of other TCP programs running on your computer all of which are using random ports when creating outbound connections, you need to be very careful about setting an arbitrary port, as it may be in use.
 
Ok, I don't want to define it, I want at least to know it. I'm writing a program for DCC Chat and it is very necessary to know the local port through which the data is being sent, because that's the same port the other user will send me his reply. According to the Delphi documentation, it should be stored in the tcpclient.localport property, but this seems to be empty all the time.

Oh, and btw, i'm talking about the tcpclient in the "internet" tab, not the "indy" one. My mistake :)
 
I'm lost here. Not sure about what is the doubt.

Short answer: it is the port you connected to/listened on.

Long answer: to inititate a connection you need to connect to a server of sorts (a central server or the other point which is acting as a server to start the data exchange). So you need to know the port where the server is listening.

All further exchange will be made thru that port. So, if your server is listening in, say, port 4000, you need to "bound" your client socket to port 4000 and all the talking will be made thru it.

What I'm saying is: you knows the port up front, as you connected to the server listening socket.

On the other side, if the remote point is starting the connection, you knows the port too, as you are the one listening in a known port (and spawning a server-client socket).

Anyway, all the data flows thru the socket you instantiated (manually if you are the client or automatically if you are the server), no need to knows the port other than to connect/listen.

May be I'm lossing your point. If you are talking about opening secondary channels (ports) after the connection is established with the listening (server) port, it is all about the negotiation protocol you are using.

Can you clarify further, please? For start, knowing if you are the client or the server can make the explanation easy to understand.

buho (A).

 
Sorry, I forgot you say you are using a TCPClient.

You are connecting to some remote IP/port where a server is listening. The port you are talking thru is the port you connected. All data will be conducted thru that port. it is the port you are using.

buho (A).
 
momtchil,

it sounds to us like you don't understand how communication between two programs via TCP works. There's lots of primers out there on the web, but here's a quick overview.

You have two programs: C and S. C contains a TCPClient component, and S contains a TCPServer component. It is totally impossible for S to initiate communication with C.

S uses a known port (eg. 80) which must be known by C.

When C wishes to communicate with S, it uses a random port that is currently not being used - (eg. 10245). C knows it has to talk to port 80 on the computer that's running S. Once communication is established, both S and C can talk to each other until the connection is dropped, S talks to C via port 10245, and C talks to S via port 80.

Once the connection is dropped, S cannot initiate communication with C via port 10245, because C is no longer listening. In fact, any other program may have started to use port 10245 instead.
 
lol first of all I want to thank everyone for being so interested in my problem :)

And second, I don't think i've expressed myself correctly. I did what I wanted with thew Indy Client and the BoundPort property, but now I have different problem. So, the DCC Chat negotiation goes like this:
1. Client A wants to DCC Chat with Client B
2. Client A sends Client B his IP and the port he's listening on (let's say Port A) via the IRC server
3. Now Client B has to indicate to Client A his IP and his port. He does that by establishing a TCP Connection to Client A on Port A and sending a message. When Client A receives the message, he also receives the IP of Client B and the port through which Client B has sent this message (Port B).
4. Client A sends messages through Port A to Client B's Port B and the opposite.

Now, the new problem is that Client B (me) has to have a TCP Client sending messages through Port B and at the same time a TCPServer listening on the same port, which appears to be impossible.
If I first set the TCPServer to listen, when I try to connect the TCPClient a mistake is raised. And if I first connect the TCPClient and then set the TCPServer, the last one doesn't accept any packages on Port B, although according to the sniffer Client A is sending data to Port B.

To make things clearer, here is the DCC Chat documentation:

and the two codes I tried to implement:
-----------------1---------------------
IdTCPClient1.BoundPort=1666;
IdTCPClient1.Host:=ip;
IdTCPClient1.Port:=port;
IdTCPClient1.Connect;
IdTCPClient1.WriteLn('');
idtcpclient1.Disconnect;

tcpserver1.LocalPort:=inttostr(IdTCPClient1.BoundPort);
tcpserver1.Active:=true; // but TCPServer.Accept dosen't get triggerred at all
---------------------end----------------

------------------2-----------------
IdTCPClient1.BoundPort=1666;

tcpserver1.LocalPort:=inttostr(IdTCPClient1.BoundPort);
tcpserver1.Active:=true;

IdTCPClient1.Host:=ip;
IdTCPClient1.Port:=port;
IdTCPClient1.Connect; // exception...
IdTCPClient1.WriteLn('');
--------------------end---------------


I'm sure this can happen, because Client A (an xdcc bot) somehow manages to send and receive data thru the same port!
 
You can't have a server and client on the same port.

Code:
IdTCPClient1.BoundPort=1666;
tcpserver1.LocalPort:=inttostr(IdTCPClient1.BoundPort);

This is where problems happen, as soon as TCPServer1 becomes active, it will open port 1666. But if you then try to IdTCPClient1.Connect, it will also try to open port 1666 - but cannot.

Whenever two programs want to talk to each other (both have a client and a server component) you must have a total of 4 ports in use, albeit not all at the same time.

If you want to set up a chat system, where both computers are using identical versions of the chat program, have them both communicate to a third server program (possibly your IRC server) where they logon and store their IP address and Port number of their TCPServer component.

When your chat program wants to communicate for the first time (cache the information for subsequent chats if you like) have it contact the third server program for the IP address of the person you want to chat to, as well as the port number their chat program is listening on. Then set those details into your TTCPClient component and Connect. you then have a communication session which can be disconnected at any time and re-established after the Send buffer has been emptied.

This method works perfectly for the second chat program wanting to send text to the first. Both can establish outgoing communications that don't interfere with each other.
 
Having now just had a look at the DCC page you linked to, I can see that you want to avoid having the third server program, which is fine - you now simply need another way to make sure of the IP address and the listening port of the other chat program.

But - it doesn't change anything else I said above.
 
Lost again with the port negotiation :(.

Sorry, I'm very pressed this week; will try to come back to this thread in a couple days if you have not solved the problem.

Anyway, you are in good hands with Griffyn.

buho (A).
 
Griffyn, you said "You can't have a server and client on the same port" and now I'm also positive it can't happen the way I'm trying to do it. Anyway, here is a log of the sniffer-program in screenshots, with comments. Open them one by one. As you see, the remote computer (User2, as I've written) can do it and wants me to do it too.


I'm sure you can figure it out :) 10x in advance...again
 
Close the listening port as far the connection is established.

buho (A).

 
Sorry, still asleep. :(

1) "as far the connection" is to be "as SOON the connection".

2) Beware the server socket class you are using. Most of "high level" classes use to close all the client-server sockets when the listening socket is closed (kinda "shutting down all the server"). Usually those classes have some messaging mechanism which calls you every time a child client-server socket is needed; you can use the creation event to create a non-child client-server socket and close the listener. (Be prepared to dig into the class source code, it can be hard to tackle... or not, depending on how the class is designed).

buho (A).
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top