Arokh Posted April 11, 2006 Posted April 11, 2006 Hi Since I made myself comfortable in VB 05 and it is going well so far, I want to give a try to make some chatclient & -server. So far I accomplished, by reading through the forum and the msdn, to make a TcpListener and TcpClient by copying the code. I already made some experiments with it and changed the code to make it more useful for my purposes. Imports System Imports System.IO Imports System.Net Imports System.Net.Sockets Imports System.Text Imports Microsoft.VisualBasic Public Class frmClient Public Client As New TcpClient Public Stream As NetworkStream Private Sub Connect(ByVal server As [string], ByVal port As Int32) Try Client.Connect(server, port) Stream = Client.GetStream Catch e As ArgumentNullException Debug.Print("ArgumentNullException: {0}", e) Catch e As SocketException Debug.Print("SocketException: {0}", e) End Try Debug.Print(ControlChars.Cr + " Press Enter to continue...") End Sub Private Sub SendMsg(ByVal Message As String) Dim data As [byte]() = System.Text.Encoding.ASCII.GetBytes(Message) Stream.Write(data, 0, data.Length) Debug.Print("Sent: {0}", Message) End Sub Private Sub CloseConnection() Client.Close() End Sub Private Function RecieveMsg() As String Dim Data = New [byte](256) {} Dim responseData As [string] = [string].Empty Dim bytes As Int32 = Stream.Read(Data, 0, Data.Length) responseData = System.Text.Encoding.ASCII.GetString(Data, 0, bytes) Debug.Print("Received: {0}", responseData) RecieveMsg = responseData End Function Private Sub frmClient_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Connect("127.0.0.1", 13000) SendMsg("Bla") RecieveMsg() CloseConnection() End Sub End Class Imports System Imports System.IO Imports System.Net Imports System.Net.Sockets Imports System.Text Imports Microsoft.VisualBasic Public Class frmServer Public stream As NetworkStream Public Sub Main() Try Dim port As Int32 = 13000 Dim localAddr As IPAddress = IPAddress.Parse("127.0.0.1") Dim server As New TcpListener(localAddr, port) server.Start() Dim bytes(1024) As [byte] Dim data As [string] = Nothing While True Debug.Print("Waiting for a connection... ") Dim client As TcpClient = server.AcceptTcpClient() Debug.Print("Connected!") data = Nothing stream = client.GetStream() Dim i As Int32 i = stream.Read(bytes, 0, bytes.Length) While (i <> 0) data = System.Text.Encoding.ASCII.GetString(bytes, 0, i) Debug.Print([string].Format("Received: {0}", data)) data = data.ToUpper() Dim msg As [byte]() = System.Text.Encoding.ASCII.GetBytes(data) stream.Write(msg, 0, msg.Length) Debug.Print([string].Format("Sent: {0}", data)) i = stream.Read(bytes, 0, bytes.Length) End While End While Catch e As SocketException Debug.Print("SocketException: {0}", e) End Try Debug.Print(ControlChars.Cr + "Hit enter to continue...") Console.Read() End Sub 'Main Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Main() End Sub End Class With this I could connect to the TCPListener send some message, then the Listener would send a message back and the client recieves it. But this only works when each side gets an answer otherwise it waits forever. Since I have to be able to get and send messages, for a Chatclient, simutanously this isn't the best solution :). I've read that I have to make an asynchronous connection, but I couldn't find enough information to get me started. So besides some tutorials you could link me to, I have some questions: 1. If I make an asynchronous connection can I recieve and send data/text with only one open port from more then one IP? I guess thats the case since for programs like mIRC, µTorrent only need one port. Is that only possible asynchronous connection? 2. What is the main reason for a Synchronous connection? (File Transfering?) 3. Does stream.Read(bytes, 0, bytes.Length) return the value of bytes still unread in the stream? If so why doesn't it leave the loop? 4. What happens after Stream.Write(data, 0, data.Length) is called in the client? Does it send the data/text right through the servers port? For example when the client send a message, closes the connection before the server has recieved the message, what happens? 5. When the server "sends" a message, does it actually send it or does the client look after such messages and pulls them from the server? Quote
Administrators PlausiblyDamp Posted April 12, 2006 Administrators Posted April 12, 2006 Typically you would use threading to get round the problem of blocking, a single listener would wait for incomming connections and spawn a new thread to handle the communication - search these forums and you should find some examples. Regardless of asynchronus or synchronus connections if you are using TCP then it is a single IP/Port to a single IP/Port - there isn't a way to have multiple connections using the same port (this isn't the same if you are using UDP based broadcasts or multicast packets though). The main reason for synchronus connections is simplicity - you do not have to worry about responding to incomming data etc. Stream.Read returns the number of bytes read into the buffer - for network connections there is no simple way to determine how much data is left as the other end could keep adding more data anyway... Stream.Write sends the data to the underlying connection, closing the stream will flush any unsent data... http://msdn2.microsoft.com/en-US/library/system.io.stream(VS.80).aspx may be worth a read regarding the Stream class. http://www.cisco.com/warp/public/535/4.html and http://www.doc.ic.ac.uk/~ih/doc/pc_conn/tcpip/intro/intro0.html are probably also worth reading as they will answer some of the networking questions. Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
Arokh Posted April 13, 2006 Author Posted April 13, 2006 Thank you for answering all my questions. But I'm quiet confused with this statement: Regardless of asynchronus or synchronus connections if you are using TCP then it is a single IP/Port to a single IP/Port - there isn't a way to have multiple connections using the same port Because a Program like µTorrent (Bittorrent client) only uses one port to communicate with several other connections. At least I think so, I set µTorrent up to a specific port and forwarded that port so the firewall allows incoming connections. The other ports are blocked. So wouldn't that mean only one other client could simutanously send me data (which isn't the case)? I've downloaded a program that lists all active ports and it only confused me more. It showed that more than one client is connected to my forwarded port (7525). The odd thing is it also shows ports which I didn't forwarded and should be blocked. ... (all TCP connections) utorrent.exe 192.168.1.2:7525 218.212.14.4:62452 ESTABLISHED utorrent.exe 192.168.1.2:7525 218.212.11.113:2739 ESTABLISHED utorrent.exe 192.168.1.2:7525 219.129.49.132:2633 ESTABLISHED utorrent.exe 192.168.1.2:7525 220.127.9.33:2327 ESTABLISHED utorrent.exe 192.168.1.2:7525 220.236.148.182:61584 ESTABLISHED utorrent.exe 192.168.1.2:7525 220.239.223.166:2960 ESTABLISHED utorrent.exe 192.168.1.2:4899 198.166.13.26:6346 ESTABLISHED utorrent.exe 192.168.1.2:4264 86.104.211.80:32459 ESTABLISHED utorrent.exe 192.168.1.2:3541 82.83.102.18:6881 ESTABLISHED utorrent.exe 192.168.1.2:3225 220.253.23.182:49153 ESTABLISHED ... It seems I have a completely wrong picture of how these things work, which is giving me a hard time. I thought that only one port is needed to establish a connection and to send and recieve data. But now I understand it is needed to have one open port on each side? Something like this? ---- ---- |PC|-->Outgoing Port(1234)-->Internet-->Incoming Port(5678)-->|PC| ---- ---- Does the direction matter, is the following also correct on the same connection? ---- ---- |PC|<--Incoming Port(1234)<--Internet<--Outgoing Port(5678)<--|PC| ---- ---- Since I thought only the incoming port is necessary, how is the incoming port chosen? When the port is randomly chosen and it is coincidently the port I have set for µTorrent and I start µTorrent, does that mean µTorrent can't use the port anymore? Back to the praktical part: When I understand you correctly, the server listens for incoming connections, then if it gets one, it tells the client to connect to different port (given by the server), after that the initial connection is closed so the server can listen for other connection requests. Since I understand it there is no incoming or outgoing port, it just tells if data is recieved oder sent, it would mean that the server has to have a great range of ports open and the client has also to forward a port to be able to send data to the server instead of just to be able to recieve it. Because a firewall blocks all incoming traffic by default. I've made a little draft to show how I would do the threading on the server- and clientside, just to be sure it is the right way to go. Since I've never programmed any applications with multithreading I've been reading on it in the msdn. Now I'm experimening with it. http://home.arcor.de/dvdkhl/Programming/Network.png Quote
Administrators PlausiblyDamp Posted April 19, 2006 Administrators Posted April 19, 2006 The port a process 'listens' on is how a client will make it's initial connection, i.e. a web server listens (by default anyway) on port 80. When a client needs to communicate with the server it will make it's initial connection to the server on this port. As part of the connection handshake the client and server will negotiate another set of port numbers to communicate on and these are the ports used for the remainder of the conversation. These 'negotiated' port numbers are not however treated as new connections as they are part of the existing connection that happened to start on port 80 - therefore they are not blocked by your firewall etc. as they are not 'incoming requests'. The scenario I suggested above of using seperate threads for each connection will work but this can cause scalability issues if the number of connections gets large as you will end up with a large number of threads, a lot of which will be idle for large portions of the time. In this scenario rather than a 'one client = one thread' model you would find using async sockets more scalable as you would only need to allocate resources as and when data arrives. Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.