missing first transmission

Started by
3 comments, last by capn_midnight 18 years, 4 months ago
I'm attempting to write a P2P network with a binary tree structure (haven't decided yet if I will make it a B-tree or not). Network programming is not something I've done a lot with, so maybe I'm missing something basic here. Anyway, each node in the network creates a listener for 2 client connections and may or may not connect to a parent node. Really simple, binary tree. When a client connects to a parent node, the parent node is supposed to immediately send it's status, followed by receiving the client's status. Naturally, the client expects it in this order as well, receive the parent node's status, then send its own status. Unfortunately, it seems the client is missing the server's status. The server will send its status, and then proceed to waiting for the client's status, but the client will be stuck waiting for the server's status. okay, some code. when a parent node accepts a connection (i is the index of the first open slot, there are only two. It's done in a for loop in case I ever want to make this an n-ary tree):

Console.WriteLine("Accepting connection #{0}", i);
connClient = connServer.AcceptTcpClient();
NetworkStream stream = connClient.GetStream();
rdrClient = new StreamReader(stream);
wrtClient = new StreamWriter(stream);
Console.WriteLine("Sending server information");
wrtClient.Write("[name {0}]", userName);
wrtClient.Flush();
Console.WriteLine("Waiting for response from client");
strClient = rdrClient.ReadLine();  //  <--- server stalls here
connectionMade = true;
Console.WriteLine("Connection made.");

when a client connects to a parent (input is in the form "address:port")

string[] parts = input.Split(":".ToCharArray());
Console.WriteLine("Connecting to {0} on port {1}.", parts[0], parts[1]);
connClient[0] = new TcpClient(parts[0], int.Parse(parts[1]));
NetworkStream stream = connClient[0].GetStream();
rdrClient[0] = new StreamReader(stream);
wrtClient[0] = new StreamWriter(stream);
Console.WriteLine("Waiting for response from server.");
string temp = rdrClient[0].ReadLine();   // <---  client stalls here
Console.WriteLine("Received message from server:\"{0}\"", temp);
//snipped some special handling in case the parent node is full
strClient[0] = temp.Substring(temp.IndexOf(" ")+1, temp.IndexOf("]"));
Console.WriteLine("Connection made, server named \"{0}\".", strClient[0]);
wrtClient[0].Write(userName);
wrtClient[0].Flush();
return true;

[Formerly "capn_midnight". See some of my projects. Find me on twitter tumblr G+ Github.]

Advertisement
server writing:
wrtClient.Write("[name {0}]", userName);
wrtClient.Flush();

client reading:
string temp = rdrClient[0].ReadLine();

I assume that RealLine waits for a terminating newline. Is the server really sending it?
Quote:Original post by doho
server writing:
wrtClient.Write("[name {0}]", userName);
wrtClient.Flush();

client reading:
string temp = rdrClient[0].ReadLine();

I assume that RealLine waits for a terminating newline. Is the server really sending it?


that's an interesting thought!

and most assureadly the problem. Thanks, now to mull on new bugs.

[Formerly "capn_midnight". See some of my projects. Find me on twitter tumblr G+ Github.]

sounds difficult
Actually, it's not too difficult. The hardest part is wrapping my head around the structure of the network. I've been able to create the binary tree structure of connections, and I've also been able to redirect a client that attempts to connect to a full node.

for example, say I have this tree and someone tries to connect to the root node ('-' is an empty connection).
     a   /   \              | (these bars here are a work around for a forum bug)  b     c / \   / \            |-   - d   -


node A will halt the incoming connection and return a list of its children. By recursing on that list, the client can perform a depth-first search of the tree, until it reaches an empty spot. In this case, it will be the left node of b.

I need to do some major refactoring, but after that I think I will work on handling dropped connections (what happens to a branch when the parent of the branch leaves?) and then get some communication between the nodes (sharing of names, I think). That will all probably be about twice as much code as I have right now.

I'm thinking the best way to handle a dropped connection is wo use a leaf node to plug the gap. Take this tree:
     a   /   \                   |  b     c / \   / \                 |d   e f   g

If node A drops the connection, this splits the b and c branches. Instead of promoting b or c and shuffling connections around to get everthing in place, I think the easiest answer is to select one of the leaf nodes to plug the whole.
     d   /   \                   |  b     c / \   / \                 |-   e f   g

Each node will ideally maintain a complete image of the tree with IP numbers for each of the nodes, but only maintain connections with at most 3 other nodes. It will be a very high latency network (a message from node D to node G must first travel up the tree before then propogating down the tree), but it should be fairly robust if I can work out the dropped connection problem.

Eventually, the network should become a hydra beast of connection points. The idea is that an attempted connection on any one node of the network will eventually lead you to an open spot.

I'm somewhat worried about an ingrown tree, but my initial mullings on the subject indicate it's not possible.
a---b|\ /|| x ||/ \|c---d

a node is only allowed to specify its parent connection (or none, if one is not available). The only way this could happen is if a node can arbitrarily redefine its parent node. The only situation in which I can imagine wanting to allow this action is if I want two developed trees to be able to join each other.

[Formerly "capn_midnight". See some of my projects. Find me on twitter tumblr G+ Github.]

This topic is closed to new replies.

Advertisement