C# networking TcpClient
Can someone tell me why "Went Through?" gets printed only when argument to Thread.Sleep is < 110?
Update <7.X.2011 5PM ET>: I think what is happening is that the server end is being saturated with client Write(a)'s which then somehow impacts the ability to send data before the connection is closed. Maybe network read buffer is being filled up?
Whenever the iteration count gets above 165xx, the "Went Through?" is not sent, anytime iteration count is <165xx, the string gets sent. This number is reached at Sleep of 107 and onward. Sleep value of 107 sends the string sometimes, depending on other (OS) threads running in the background.
The iteration value never gets above 165xx, even when Sleep is set to a large value (say 2sec), which leads me to believe the network buffer is full.
static void fClient()
{
int iterations = 0;
TcpClient client = new TcpClient("localhost", 22320);
BinaryReader br = new BinaryReader(client.GetStream());
BinaryWriter bw = new BinaryWriter(client.GetStream());
while (true)
{
try
{
if (client.Available > 0)
{
Console.WriteLine(br.ReadString());
}
else
{
bw.Write("a");
iterations++;
}
}
catch (IOException)
{
Console.WriteLine("EXCEPTION");
//exception always reads: Unable to write....
// (thrown by bw.Write("a"))
// show iterations count
break;
}
}
}
stat开发者_开发技巧ic void Main(string[] args)
{
TcpListener server = new TcpListener(22320);
server.Start();
new Thread(fClient).Start();
Thread.Sleep(200);
TcpClient client = server.AcceptTcpClient();
BinaryWriter binWrite = new BinaryWriter(client.GetStream());
binWrite.Write("Went Through?");
binWrite.Flush();
client.Close();
}
I also think the code is straightforward:) But this one doesn't use Sleep to synchronize threads.
static Semaphore Go = new Semaphore(0, 1);
static void Server()
{
TcpListener server = new TcpListener(22320);
server.Start();
Go.Release();
while (true)
{
TcpClient client = server.AcceptTcpClient();
new Thread((x) => ServerTask(x)).Start(client);
}
}
static void ServerTask(object clnObj)
{
TcpClient client = clnObj as TcpClient;
BinaryReader br = new BinaryReader(client.GetStream());
BinaryWriter bw = new BinaryWriter(client.GetStream());
string s = "FromServer: " + br.ReadString();
bw.Write(s);
client.Close();
}
static void Client(int i)
{
TcpClient client = new TcpClient();
client.Connect("localhost", 22320);
BinaryReader br = new BinaryReader(client.GetStream());
BinaryWriter bw = new BinaryWriter(client.GetStream());
bw.Write(i.ToString());
Console.WriteLine(br.ReadString());
client.Close();
}
static void Main(string[] args)
{
Thread t = new Thread(() => Server());
t.IsBackground = true;
t.Start();
Go.WaitOne();
Console.WriteLine("Server Started....");
Parallel.For(0, 21, (i) => Client(i));
Console.WriteLine("Clients Processed");
Console.ReadLine();
}
I think I finally figured this out.
Two endpoints A and B talking to each other: A <-> B
When A sends a message to B and then closes its TcpClient object, I assumed that the TcpClient.Available property on B will still list that last message from A as received and then BinaryReader.ReadString() would be able to retrieve that message, even though the TCP/IP connection was broken by A.
I observed, that that was not always the case and now I think I understand why.
After A closes connection, if B only does reads from network, then it will be able to grab that last message from A and Available property will reflect that message's presence. But if B does a write to the network, then that write will instantly detect a broken connection and fail any subsequent reads/writes, even if Available property returns >0.
So in fact I did understand Available property correctly, but learned today that there are exceptions, when the property will not behave as expected.
If I'm wrong, please correct me. Now onto changing my app.
精彩评论