C# Connecting two tcp sockets together - c#

I'm not sure if the title is all that informative.
I am trying to find/write a socket server that will accept a connection from the client (telnet) and then on behalf of the connected client, connect to one of four telnet servers inside the network.
Once connected I keep a counter of how many connections there are, and then if there are 4 total connections, disallow any new connections until one of the four is available.
I have written this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.Net;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static int nodeCount = 4;
static int currentNode = 1;
static void Main(string[] args)
{
ServerProgram server = new ServerProgram();
}
class ServerProgram
{
private TcpListener tcpPrimaryListener;
private Thread listenThread;
public ServerProgram()
{
this.tcpPrimaryListener = new TcpListener(IPAddress.Any, 23);
Console.WriteLine("Telnet BBS Port Concentrator Server Started.");
Console.WriteLine("--------------------------------------------");
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
}
private void ListenForClients()
{
this.tcpPrimaryListener.Start();
while (true)
{
TcpClient client = this.tcpPrimaryListener.AcceptTcpClient();
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}
private void HandleClientComm(object client)
{
if (currentNode <= nodeCount)
{
Console.WriteLine("Connection thread created.");
StreamWriter swStream;
StreamWriter swStream2;
StreamReader srStream;
StreamReader srStream2;
TcpClient tcpClient = (TcpClient)client;
NetworkStream tcpClientStream = tcpClient.GetStream();
TcpClient telnet = new TcpClient("192.168.100.5" + currentNode, 23);
NetworkStream telnetStream = telnet.GetStream();
currentNode++;
while (true)
{
srStream = new StreamReader(tcpClient.GetStream());
swStream2 = new StreamWriter(tcpClient.GetStream());
srStream2 = new StreamReader(telnet.GetStream());
swStream = new StreamWriter(telnet.GetStream());
swStream.Write(srStream.ReadToEnd());
swStream2.Write(srStream2.ReadToEnd());
}
}
}
}
}
}
I've changed this example multiple times, so I don't really know anymore what I have and have not tried. I'm willing to try anything.
The purpose is actually running this to allow one telnet port open through the firewall, and allowing connections into a small network of DOS machines running telnet fossil driver BBS software. I would just like to redirect telnet traffic to an available system using only one port.
The problem is that I cannot figure out how to actually connect the two sockets together and pass data between them as it happens. The incoming socket and the socket I created on behalf of the server to the server.
Thanks.
UPDATE:
This is what is working for me, I'm still looking over for bugs but it's working so far.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.Net;
using System.IO;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static int nodeCount = 2;
static int currentNode = 1;
static void Main(string[] args)
{
ServerProgram server = new ServerProgram();
}
class ServerProgram
{
private TcpListener tcpPrimaryListener;
private Thread listenThread;
public ServerProgram()
{
this.tcpPrimaryListener = new TcpListener(IPAddress.Any, 23);
Console.WriteLine("Telnet BBS Port Concentrator Server Started.");
Console.WriteLine("--------------------------------------------");
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
}
private void ListenForClients()
{
this.tcpPrimaryListener.Start();
while (true)
{
TcpClient client = this.tcpPrimaryListener.AcceptTcpClient();
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}
private void HandleClientComm(object client)
{
string noNodes = "Sorry all nodes are occupied.";
if (currentNode <= nodeCount)
{
Console.WriteLine("Client connected.");
TcpClient tcpClient = (TcpClient)client;
NetworkStream tcpClientStream = tcpClient.GetStream();
TcpClient telnet = new TcpClient("10.24.9.11", 23);
//TcpClient telnet = new TcpClient("192.168.100.5" + currentNode, 23);
NetworkStream telnetStream = telnet.GetStream();
currentNode++;
ByPass linkedSockets = new ByPass(tcpClientStream, telnetStream);
}
else
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream tcpClientStream = tcpClient.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
tcpClientStream.Write(Encoding.ASCII.GetBytes(noNodes), 0, noNodes.Length);
}
}
}
public class ByPass
{
public ByPass(Stream s1, Stream s2)
{
var cTokenSource = new CancellationTokenSource();
var cToken = cTokenSource.Token;
Task.Factory.StartNew(() => Process(s1, s2, cToken, cTokenSource), cToken);
Task.Factory.StartNew(() => Process(s2, s1, cToken, cTokenSource), cToken);
cToken.Register(() => cancelNotification());
}
public void Process(Stream s1, Stream s2, CancellationToken ct, CancellationTokenSource cTokenSource)
{
byte[] buf = new byte[0x10000];
while (true)
{
if (ct.IsCancellationRequested)
{
break;
}
try
{
int len = s1.Read(buf, 0, buf.Length);
s2.Write(buf, 0, len);
}
catch
{
s1.Close(); s2.Close();
cTokenSource.Cancel();
break;
}
}
}
}
static void cancelNotification()
{
Console.WriteLine("Client disconnected.");
currentNode--;
}
}
}

I think, you can create a class similar to below to pass data between two streams
public class ByPass
{
public ByPass(Stream s1, Stream s2)
{
Task.Factory.StartNew(() => Process(s1, s2));
Task.Factory.StartNew(() => Process(s2, s1));
}
public void Process(Stream sIn, Stream sOut)
{
byte[] buf = new byte[0x10000];
while (true)
{
int len = sIn.Read(buf, 0, buf.Length);
sOut.Write(buf, 0, len);
}
}
}

I have made little changes and it works perfect on my side
public class StreamTransmitter
{
static TaskCompletionSource<bool> ts;
public static async Task Start(Stream s1, Stream s2, CancellationToken token)
{
ts = new TaskCompletionSource<bool>();
Process(s1, s2, token);
Process(s2, s1, token);
await ts.Task;
}
private static async Task Process(Stream sIn, Stream sOut, CancellationToken token)
{
byte[] buf = new byte[0x10000];
int len = 0;
do
{
len = await sIn.ReadAsync(buf, 0, buf.Length, token);
await sOut.WriteAsync(buf, 0, len, token);
}
while (len > 0 && !token.IsCancellationRequested);
ts.SetResult(true);
}
}

Related

C# Build simple server with event when new client connected

I tried to build a simple server in c# which wait for connections from clients. If a new client connects it makes a new Thread where it read from the client and send a message back to the client, that the server received the message from the client. My problem is that I try to raise an event when a new client connected to the server, but I just don't get what I should subscribe to.
Here is my code:
namespace ChatServer
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Threading;
class Program
{
public static event EventHandler<NewClientConnectedEventArgs>NewClientConnected;
public static void Main(string[] args)
{
TcpListener listener = new TcpListener(IPAddress.Any, 80);
listener.Start();
while (true)
{
TcpClient client = listener.AcceptTcpClient();
//listener += NewClientConnected(null, new NewClientConnectedEventArgs(client));
//FireNewClientHasConnected(null, eventargs);
}
}
public static void MakeNewConnection(TcpClient client)
{
Thread thread = new Thread(new ParameterizedThreadStart(NewClient));
thread.Start(client);
}
public static void NewClient(object data)
{
TcpClient client = (TcpClient)data;
string adress = client.Client.AddressFamily.ToString();
Console.WriteLine("{0} has connected!", adress);
NetworkStream ns = client.GetStream();
while (true)
{
byte[] receivedbuffer = new byte[8192];
int receivedbytes;
receivedbytes = ns.Read(receivedbuffer, 0, receivedbuffer.Length);
string message = Encoding.UTF8.GetString(receivedbuffer, 0, receivedbytes);
string newmessage = "The server received: " + message;
byte[] sendBuffer = Encoding.UTF8.GetBytes(newmessage);
ns.Write(sendBuffer, 0, sendBuffer.Length);
}
}
protected static void FireNewClientHasConnected(object sender, NewClientConnectedEventArgs args)
{
if (NewClientConnected != null)
{
MakeNewConnection(args.Client);
}
}
}
The part where I have the problem is the part which I comment out. Thanks in advance!
The call listener.AcceptTcpClient() blocks until a client connected. So just fire the event after the listener accepted the client.
class Program
{
public static void Main(string[] args)
{
var listener = new TcpListener(IPAddress.Any, 80);
listener.Start();
while (true)
{
TcpClient client = listener.AcceptTcpClient();
MakeNewConnection(client);
}
}
public static void MakeNewConnection(TcpClient client)
{
var thread = new Thread(NewClient);
thread.Start(client);
}
public static void NewClient(object data)
{
var client = (TcpClient)data;
string adress = client.Client.AddressFamily.ToString();
Console.WriteLine("{0} has connected!", adress);
NetworkStream ns = client.GetStream();
while (true)
{
byte[] receivedbuffer = new byte[8192];
int receivedbytes = ns.Read(receivedbuffer, 0, receivedbuffer.Length);
string message = Encoding.UTF8.GetString(receivedbuffer, 0, receivedbytes);
string newmessage = "The server received: " + message;
byte[] sendBuffer = Encoding.UTF8.GetBytes(newmessage);
ns.Write(sendBuffer, 0, sendBuffer.Length);
}
}
}

TcpListener send heartbeat every 5 seconds and read message from client async

I'm writing a TcpListener service that runs as a Windows Service that a vendor software client will connect to. I can't change the client's implementation and must adhere to their spec.
I have the part that receives messages and returns a response working. The problem I have is the clients expect a heartbeat message (S0000E) to be sent every 5 seconds, to which it replies with the same message. I'm not sure how to add that functionality in among the async/await stuff I'm doing to handle the real messages received from the clients.
OnStart
_serverListenerTask = Task.Run(() => AcceptClientsAsync(_listener, _cancellationToken.Token));
AcceptClientsAsync
static async Task AcceptClientsAsync(TcpListener listener, CancellationToken ct)
{
var clientCounter = 0;
while (!ct.IsCancellationRequested)
{
TcpClient client = await listener.AcceptTcpClientAsync()
.ConfigureAwait(false);
clientCounter++;
await ReceiveMessageAsync(client, clientCounter, ct);
}
}
ReceiveMessageAsync
static async Task ReceiveMessageAsync(TcpClient client, int clientIndex, CancellationToken ct)
{
Log.Info("New client ({0}) connected", clientIndex);
using (client)
{
var buffer = new byte[4096];
var stream = client.GetStream();
while (!ct.IsCancellationRequested)
{
var timeoutTask = Task.Delay(TimeSpan.FromSeconds(15));
var amountReadTask = stream.ReadAsync(buffer, 0, buffer.Length, ct);
var completedTask = await Task.WhenAny(timeoutTask, amountReadTask)
.ConfigureAwait(false);
if (completedTask == timeoutTask)
{
var msg = Encoding.ASCII.GetBytes("Client timed out");
await stream.WriteAsync(msg, 0, msg.Length);
break;
}
var bytesRead = amountReadTask.Result;
if (bytesRead == 0)
{
// Nothing was read
break;
}
// Snip... Handle message from buffer here
await stream.WriteAsync(responseBuffer, 0, responseBuffer.Length, ct)
.ConfigureAwait(false);
}
}
Log.Info("Client ({0}) disconnected", clientIndex);
}
I thought I could add a heartbeat task to the Task.WhenAny, but that caused the heartbeat to always fire and I could never read the response. I also tried sending the heartbeat before the timeout and read tasks, which worked for sending, but then I was either reading the heartbeat response and not the next message in line or the timeout task would complete and disconnect the client. Essentially, if the heartbeat exchange is successful then the client shouldn't be disconnected after that 15 second delay.
Implementing TCP server-client is not a simple task. However, the following way of implementation, if you improve it to be more efficient in resources, can be a practical solution:
Server:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Server
{
public class Program
{
static List<SocketBuffer> clients = new List<SocketBuffer>();
public static void Main(string[] args)
{
//Receive from any IP, listen on port 65000 in this machine
var listener = new TcpListener(IPAddress.Any, 65000);
var t = Task.Run(() =>
{
while (true)
{
listener.Start();
var task = listener.AcceptTcpClientAsync();
task.Wait();
clients.Add(new SocketBuffer(task.Result, new byte[4096]));
}
});
t.Wait(); //It will remain here, do in a better way if you like !
}
}
/// <summary>
/// We need this class because each TcpClient will have its own buffer
/// </summary>
class SocketBuffer
{
public SocketBuffer(TcpClient client, byte[] buffer)
{
this.client = client;
stream = client.GetStream();
this.buffer = buffer;
receiveData(null);
}
private TcpClient client;
private NetworkStream stream;
private byte[] buffer;
private object _lock = new object();
private async void receiveData(Task<int> result)
{
if (result != null)
{
lock (_lock)
{
int numberOfBytesRead = result.Result;
//If no data read, it means we are here to be notified that the tcp client has been disconnected
if (numberOfBytesRead == 0)
{
onDisconnected();
return;
}
//We need a part of this array, you can do it in more efficient way if you like
var segmentedArr = new ArraySegment<byte>(buffer, 0, numberOfBytesRead).ToArray();
OnDataReceived(segmentedArr);
}
}
var task = stream.ReadAsync(buffer, 0, buffer.Length);
//This is not recursion in any sense because the current
//thread will be free and the call to receiveData will be from a new thread
await task.ContinueWith(receiveData);
}
private void onDisconnected()
{
//Add your code here if you want this event
}
private void OnDataReceived(byte[] dat)
{
//Do anything with the data, you can reply here. I will just pring the received data from the demo client
string receivedTxt = Encoding.ASCII.GetString(dat);
Console.WriteLine(receivedTxt);
}
}
}
Demo client:
using System;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace Client
{
public class Program
{
public static void Main(string[] args)
{
TcpClient client = new TcpClient();
var task = client.ConnectAsync("localhost", 65000);
task.Wait();
if(client.Connected)
{
Console.WriteLine("Client connected");
var stream = client.GetStream();
var data = Encoding.ASCII.GetBytes("test");
stream.Write(data, 0, data.Length);
}
else
{
Console.WriteLine("Client NOT connected");
}
Thread.Sleep(60000);
}
}
}

TCP chat client/server won't work off localhost

I am currently learning to program a chat room application that uses a server. So far everything works fine if I run the server and multiple instances of the application on a single machine. When I try to run the server on one machine and the actual chat application from another, I get an exception that reads "a connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond (Ipaddress)(port)"
Server side code:
using System;
using System.Net;
using System.Net.Sockets;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Collections;
using System.Text;
using System.Threading;
namespace ChatAppServer
{
class Program
{
public static Hashtable ClientList = new Hashtable();
const int PORT = 321;
string localIp;
static void Main(string[] args)
{
TcpListener sckServer = new TcpListener(PORT);
TcpClient sckClient = default(TcpClient);
int counter = 0;
sckServer.Start();
Console.WriteLine("Chat Server is now Running ....");
counter = 0;
//Parser myParser = new Parser();
while (true)
{
counter = counter + 1;
sckClient = sckServer.AcceptTcpClient();
string clientData = "";
byte[] recieveData = new byte[10025];
NetworkStream netStream = sckClient.GetStream();
netStream.Read(recieveData, 0, (int)sckClient.ReceiveBufferSize);
clientData = System.Text.Encoding.ASCII.GetString(recieveData);
clientData = clientData.Substring(0, clientData.IndexOf("$"));
ClientList.Add(clientData, sckClient);
Broadcast(clientData + " joined the chat", clientData, false);
Console.WriteLine(clientData + " connected to the chat");
handleClient client = new handleClient();
client.ClientStart(sckClient, clientData, ClientList);
}
sckClient.Close();
sckServer.Stop();
Console.WriteLine("exit");
Console.ReadLine();
}
public static void Broadcast(string msg, string userName, bool flag)
{
foreach (DictionaryEntry Item in ClientList)
{
TcpClient sckBroadcast;
sckBroadcast = (TcpClient)Item.Value;
NetworkStream broadcastStream = sckBroadcast.GetStream();
Byte[] broadcastData = null;
if (flag == true)
{
broadcastData = Encoding.ASCII.GetBytes(userName + ": " + msg);
}
else
{
broadcastData = Encoding.ASCII.GetBytes(msg);
}
broadcastStream.Write(broadcastData, 0, broadcastData.Length);
broadcastStream.Flush();
}
}
public class handleClient
{
TcpClient sckClient;
string clId;
Hashtable ClientList;
public void ClientStart(TcpClient inSckClient, string clientId, Hashtable clist) {
this.sckClient = inSckClient;
this.clId = clientId;
this.ClientList = clist;
Thread ctThread = new Thread(runChat);
ctThread.Start();
}
private void runChat() {
int requestCount = 0;
byte[] recieveData = new byte[10025];
string clientData = "";
string rCount = null;
while ((true))
{
try
{
requestCount += 1;
NetworkStream netStream = sckClient.GetStream();
netStream.Read(recieveData, 0, (int)sckClient.ReceiveBufferSize);
clientData = System.Text.Encoding.ASCII.GetString(recieveData);
clientData = clientData.Substring(0, clientData.IndexOf("$"));
Console.WriteLine(clId + " : " + clientData);
rCount = Convert.ToString(requestCount);
Program.Broadcast(clientData, clId, true);
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
}
}
}
Chat room application code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
//Need for the application
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace ChatApp
{
public partial class Form1 : Form
{
System.Net.Sockets.TcpClient sckClient = new System.Net.Sockets.TcpClient();
NetworkStream svrStream = default(NetworkStream);
string recieveData = null;
public Form1()
{
InitializeComponent();
btnSend.Enabled = false;
}
private void btnConnect_Click(object sender, EventArgs e)
{
recieveData = "Connected to Server";
msg();
int serverPort = Convert.ToInt32(txtServerPort.Text);
sckClient.Connect(txtServerIp.Text, serverPort);
svrStream = sckClient.GetStream();
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(txtUserName.Text + "$");
svrStream.Write(outStream, 0, outStream.Length);
svrStream.Flush();
Thread ctThread = new Thread(MessageCallBack);
btnSend.Enabled = true;
btnConnect.Enabled = false;
txtUserName.Enabled = false;
txtServerIp.Enabled = false;
txtServerPort.Enabled = false;
ctThread.Start();
}
private void MessageCallBack()
{
while(true)
{
svrStream = sckClient.GetStream();
int buffSize = 0;
byte[] inStream = new byte[10025];
buffSize = sckClient.ReceiveBufferSize;
svrStream.Read(inStream, 0, buffSize);
string returnData = System.Text.Encoding.ASCII.GetString(inStream);
recieveData = "" + returnData;
msg();
}
}
//function to display data strings
private void msg()
{
if (this.InvokeRequired)
{
this.Invoke(new MethodInvoker(msg));
}
else
{
lstMessage.Items.Add(recieveData);
}
}
private void btnSend_Click(object sender, EventArgs e)
{
byte[] outStream = System.Text.Encoding.ASCII.GetBytes(txtMessage.Text + "$");
svrStream.Write(outStream, 0, outStream.Length);
svrStream.Flush();
txtMessage.Text = "";
}
I have two troubles with your code :
Do not use .ReceiveBufferSize value because it's a different value of your byte array length. And you can have an index out of range exception.
You have a problem of concurrency in the server side. More than 1 thread try to access to the ClientList and this collection is not thread-safe.
To resolve this, you can use the lock keyword
private static object _lock = new object();
//...
lock (_lock)
{
ClientList.Add(clientData, sckClient);
}
lock (_lock)
{
Broadcast(clientData + " joined the chat", clientData, false);
}
//...
lock (_lock)
{
Program.Broadcast(clientData, clId, true);
}
As you're a beginner, i would give you some tips.
Try to use the asynchronous network functions (better than raw threads), an example there.
There is a lot of tutorials about safety with severals connections in C# (with some thing else, better, than the lock keyword).

Ident server not returning Identification on port 113

I am trying to program an ident sever to deal with the identity protocol requests from an irc server that I am programming an irc client for. The problem is I try to print to the screen the what I receive but nothing prints. I am not getting an error code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
namespace ConnectIRC
{
class IdentityClass
{
private const int bufSize = 32;
public void IdentityRequest() {
TcpListener listener = null;
int port = 113;
IPEndPoint hostInfo = new IPEndPoint(IPAddress.Any, 113);
listener = new TcpListener(hostInfo);
listener.Start();
byte[] rcvBuffer = new byte[bufSize];
int rec;
for (; ; )
{
TcpClient client = null;
NetworkStream netStream = null;
client = listener.AcceptTcpClient();
if (listener.Pending())
{
Console.WriteLine("Connection was made");
}
netStream = client.GetStream();
//byte[] rcvBuffer = new byte[bufSize];
rec = netStream.Read(rcvBuffer, 0, rcvBuffer.Length);
Array.Resize(ref rcvBuffer, rec);
Console.WriteLine(Encoding.ASCII.GetString(rcvBuffer));
netStream.Close();
client.Close();
}
}
}
}
This is a very basic implementation of an ident server
Obviously it only accepts one connection and closes
Note you'll need to have a port mapped through your router for this to work
public class Ident
{
private readonly TcpListener _listener;
private readonly string _userId;
public Ident(string userId)
{
_userId = userId;
_listener = new TcpListener(IPAddress.Any, 113);
}
public void Start()
{
Console.WriteLine("Ident started");
_listener.Start();
var client = _listener.AcceptTcpClient();
_listener.Stop();
Console.WriteLine("Ident got a connection");
using (var s = client.GetStream())
{
var reader = new StreamReader(s);
var str = reader.ReadLine();
var writer = new StreamWriter(s);
Console.WriteLine("Ident got: " + str + ", sending reply");
writer.WriteLine(str + " : USERID : UNIX : " + _userId);
writer.Flush();
Console.WriteLine("Ident sent reply");
}
Console.WriteLine("Ident server exiting");
}
}

c# client/server application only works for lans, fix? [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
tcp/ip client server not working over internet
i spent the last week working on a simple windows form application that' s supposed to send a couple of integer numbers from client to server or from server to client. So far i have only managed to make it work for lanns, any idea about how to make it work on the open internet ?
Here' s the code in case you need it (also call me noob but i can' t get how this site handles code, ... does not do what i thought it did so feel free to edit my post in case i fail2format)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace client_server_penta
{
public class Client
{
#region Fields
private int turno = 1;
private TcpClient[] clients = new TcpClient[1]; //used to remember the active client
private int CoordinateX, CoordinateY; //coordinates, they are used by the application
#endregion
public Client(string address)
{
TcpClient client = new TcpClient();
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse(address), 3000);
client.Connect(serverEndPoint);
clients[0] = client;
Thread ReadFromServer = new Thread(new ParameterizedThreadStart(this.ReadHandler));
ReadFromServer.Start(client);
}
public void SendData(int a, int b)
{
NetworkStream clientStream = clients[0].GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes(a.ToString() + '$' + b.ToString() + '$');
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
}
public int ReadCoordinateX()
{
return this.CoordinateX;
}
public int ReadCoordinateY()
{
return this.CoordinateY;
}
private void ReadHandler(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
byte[] buffer;
int bytesRead;
while (true)
{
buffer = new byte[10];
bytesRead = 0;
try
{
bytesRead = clientStream.Read(buffer, 0, buffer.Length);
}
catch
{
//an uknown error has occurred
break;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
break;
}
//data received
ASCIIEncoding encoder = new ASCIIEncoding();
OnDataReceived(encoder.GetString(buffer, 0, buffer.Length));
}
tcpClient.Close();
}
private void OnDataReceived(string text)
{
string first_number = "";
string second_number = "";
int index = 0;
while (text[index] != '$')
first_number += text[index++];
index++;
while (text[index] != '$')
second_number += text[index++];
this.CoordinateX = Convert.ToInt32(first_number);
this.CoordinateY = Convert.ToInt32(second_number);
var myForm = Application.OpenForms["Form2"] as Form2;
myForm.Text = "Turno N." + Convert.ToString(this.turno++);
}
}
}
//and here' s the server
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace client_server_penta
{
public class Server
{
private Thread listenThread;
private int turno = 1;
private TcpListener tcpListener;
private TcpClient[] clients = new TcpClient[1]; //used to remember the active client
private int CoordinateX, CoordinateY; //coordinates, they are used by the application
public Server(int port)
{
this.tcpListener = new TcpListener(IPAddress.Any, 3000);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
}
public void SendData(int a, int b)
{
NetworkStream clientStream = clients[0].GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes(a.ToString()+'$'+b.ToString()+'$');
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
}
public int ReadCoordinateX()
{
return this.CoordinateX;
}
public int ReadCoordinateY()
{
return this.CoordinateY;
}
private void ListenForClients()
{
this.tcpListener.Start();
TcpClient client = this.tcpListener.AcceptTcpClient();
clients[0] = client;
Thread ReadFromClient = new Thread(new ParameterizedThreadStart(this.ReadHandler));
ReadFromClient.Start(client);
}
private void ReadHandler(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
byte[] buffer = new byte[10];
int bytesRead;
while (true)
{
buffer = new byte[10];
bytesRead = 0;
try
{
bytesRead = clientStream.Read(buffer, 0, buffer.Length);
}
catch
{
break;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
break;
}
//data received
ASCIIEncoding encoder = new ASCIIEncoding();
OnDataReceived(encoder.GetString(buffer, 0, buffer.Length));
}
tcpClient.Close();
}
private void OnDataReceived(string text)
{
string first_number = "";
string second_number = "";
int index = 0;
while (text[index] != '$')
first_number += text[index++];
index++;
while (text[index] != '$')
second_number += text[index++];
this.CoordinateX = Convert.ToInt32(first_number);
this.CoordinateY = Convert.ToInt32(second_number);
var myForm = Application.OpenForms["Form2"] as Form2;
myForm.Text = "Turno N."+Convert.ToString(this.turno++);
}
}
}
Have you opened the 3000 port on your firewall on the two sides ?
Yes of course ^^
If you have routers, don't forget to edit the configurations too.

Categories

Resources