Hi,
I have made a port forwarder, ZA is server side, and Client is client side.
This Port Forwarder sits in middle of both, and simply sends data coming from Client to ZA, and from ZA to Client.
Its not like for every ZA packet, Client will send a response, for a particular packet from ZA, Client can send Multiple packets, and same applies vice versa.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using System.Threading;
namespace WindowsApplication1
{
public partial class PortForwarder : Form
{
private TcpListener tcpListener;
private Thread listenThread;
delegate void OutputUpdateDelegate(string data);
public void listenclientT(string data)
{
if ( listenclient.InvokeRequired )
listenclient.Invoke(new OutputUpdateDelegate(listenclientCallback),
new object[] { data });
else
listenclientCallback(data); //call directly
}
private void listenclientCallback(string data)
{
listenclient.Text = "-c-"+data;
}
public void listenserverT(string data)
{
if (listenserver.InvokeRequired)
listenserver.Invoke(new OutputUpdateDelegate(listenserverCallback),
new object[] { data });
else
listenserverCallback(data); //call directly
}
private void listenserverCallback(string data)
{
listenserver.Text = "-s-" + data;
}
public PortForwarder()
{
InitializeComponent();
this.tcpListener = new TcpListener(IPAddress.Any, 3000);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
}
private void ListenForClients()
{
this.tcpListener.Start();
while (true)
{
//blocks until a client has connected to the server
TcpClient client = this.tcpListener.AcceptTcpClient();
//create a thread to handle communication
//with connected client
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}
private void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
//
TcpClient SendToZA = new TcpClient();
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9981);
SendToZA.Connect(serverEndPoint);
NetworkStream SendToZAStream = SendToZA.GetStream();
byte[] ZAmessage = new byte[4096];
int ZAbytesRead;
int counter = 0;
int TimeOutZA = 0;
int TimeOutClient = 0;
//
byte[] message = new byte[4096];
int bytesRead;
//Time Out Property
clientStream.ReadTimeout = 5000;
SendToZAStream.ReadTimeout = 5000;
while (true)
{
bytesRead = 0;
ZAbytesRead = 0;
try
{
//blocks until a client sends a message, so timeout specified for read operation before while loop starts
bytesRead = clientStream.Read(message, 0, 4096);
TimeOutClient = 0;
}
catch (System.IO.IOException)
{
TimeOutClient = TimeOutClient + 1;
}
catch
{
//a socket error has occured
break;
}
if (bytesRead > 0)
{
SendToZAStream.Write(message, 0, bytesRead);
SendToZAStream.Flush();
}
//For Real ZA
try
{
//blocks until a ZA sends a message, so timeout specified for read operation before while loop starts
ZAbytesRead = SendToZAStream.Read(ZAmessage, 0, ZAmessage.Length);
TimeOutZA = 0;
}
catch (System.IO.IOException)
{
TimeOutZA = TimeOutZA + 1;
}
catch
{
//a socket error has occured
break;
}
ASCIIEncoding encoder = new ASCIIEncoding();
listenclientT(encoder.GetString(message, 0, message.Length));
if (ZAbytesRead > 0)
{
//message has successfully been received
listenserverT(ZAbytesRead.ToString() + "|" + encoder.GetString(ZAmessage, 0, ZAbytesRead));
clientStream.Write(ZAmessage, 0, ZAbytesRead);
clientStream.Flush();
}
if (TimeOutZA > 700 || TimeOutClient > 700)
{
//the client or real ZA has disconnected from the Port Forwarder, as 700*5000 milisecond, no successfull read operation
MessageBox.Show("-TimeOut-" + TimeOutZA + "|" + TimeOutClient, "Confirm delete", MessageBoxButtons.YesNo);
break;
}
}
SendToZAStream.Close();
SendToZA.Close();
clientStream.Close();
tcpClient.Close();
MessageBox.Show("-test- Program Terminated", "Confirm delete", MessageBoxButtons.YesNo);
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void run_Click(object sender, EventArgs e)
{
//running ran = new running();
//running.runit();
//runit();
}
}
}
I need help in HandleClientComm()
I have used ReadTimeout to time out, the read operation for every 5 seconds, so that time slot can be alloted to ZA and Client in cyclic manner. And if it doesn't find a response from any side for 5*700 sec, it tends to Close the connection.
Now, the problem is, this code works great for Readtimeout of 5000ms. But if i set ReadTimeout to small like 500ms or 1000ms, its like it doesnt go into the try block and keeps on increasing the loop timeout counter, and eventually the loop terminates very soon compared to what it actually should minimum.
I think, though not sure, that after IOException, system needs a gap time to read again from same stream.
I have Catched IOException, because it occurs due to timeout, which i used for time sharing.
Please suggest a code example solution to this, because i really need to give time slot of like 500ms or maximum 1000ms for each side, this slot of 5000ms cannot work for me.