Response from asynchronous server to asynchronous client is NULL in C# - c#

I have asynchronous communication between client and server. When the client receives a response from the server (ReceiveCallback), the response is stored in public static string response in my NetworkHandler class. I am trying to use this field in my GameHandler class, but it says that response is empty.
I am sure that my buffer in NetworkHandler is not empty, because I checked it.
I think it happens because NetworkHandler.response is called before the response gets a value, but I am not sure and I don't know how to solve it...
See the comments in the code for more explanation...
Please take a look at this image to see the null value in GameHandler: http://i.imgur.com/BPVDlhf.png And here to see the correct value in NetworkHandler: http://i.imgur.com/vfY2IuD.png
class NetworkHandler
{
public static string response = String.Empty;
private static void ReceiveCallback(IAsyncResult AR)
{
Socket remote = (Socket)AR.AsyncState;
int received = remote.EndReceive(AR);
byte[] dataBuffer = new byte[received];
Array.Copy(_buffer, dataBuffer, received);
string serverData = Encoding.ASCII.GetString(dataBuffer);
response = serverData;
}
private static void SendCallback(IAsyncResult AR)
{
Socket remote = (Socket)AR.AsyncState;
int sent = remote.EndSend(AR);
remote.BeginReceive(_buffer, 0, _size, SocketFlags.None, new AsyncCallback(ReceiveCallback), remote);
}
public static void sendData(string data)
{
byte[] message = Encoding.ASCII.GetBytes(data);
_client.BeginSend(message, 0, message.Length, SocketFlags.None, new AsyncCallback(SendCallback), _client);
}
private static void ConnectCallback(IAsyncResult AR)
{
_client = (Socket)AR.AsyncState;
try
{
_client.EndConnect(AR);
_client.BeginReceive(_buffer, 0, _size, SocketFlags.None, new AsyncCallback(ReceiveCallback), _client);
}
catch (SocketException e)
{
Console.WriteLine(e.ToString());
}
}
}
class GameHandler
{
public void StartGame()
{
// SEND DATA USING BEGINSEND()
SendData("<sg>");
// THIS VALUE IS NULL!!! :(
_response = NetworkHandler.response;
// SO CODE INSIDE IF IS NOT EXECUTED :(
if (_response != null)
{
// If you are the drawer.
if (_response.Substring(0, 5) == "<dra>")
etc.........
}
}
public void SendData(string data)
{
NetworkHandler.sendData(data);
}
}

Related

Asynchronous client / server c# problem with second communication

I´m struggling with problem that after first success full connection with sockets I can establish second without errors. What to do ? I have give there both application so you can try help me troubleshoot that problem. Thanks you very much guys!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Threading;
using System.Net;
namespace AsynchronousClientLearning
{
class Program
{
public class ObjectState
{
public const int BufferSize = 256;
public Socket wSocket { get; set; } = null;
public byte[] Buffer = new byte[BufferSize];
public StringBuilder sb = new StringBuilder();
}
public class AsyncSocketClient
{
private const int Port = 4343;
private static ManualResetEvent connectComplete = new ManualResetEvent(false);
private static ManualResetEvent sendCompleted = new ManualResetEvent(false);
private static ManualResetEvent receiveCompleted = new ManualResetEvent(false);
private static string response = String.Empty;
public static void StartClient()
{
try
{
IPHostEntry ipHost = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ip = ipHost.AddressList[0];
IPEndPoint remoteEndPoint = new IPEndPoint(ip, Port);
Socket client = new Socket(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
client.BeginConnect(remoteEndPoint, new AsyncCallback(ConnectionCallback) , client);
Send(client, "this socket message<EOF>");
sendCompleted.WaitOne();
Receive(client);
receiveCompleted.WaitOne();
Console.WriteLine($"Response received {response}");
client.Shutdown(SocketShutdown.Both);
client.Close();
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
private static void Receive(Socket client)
{
try
{
ObjectState state = new ObjectState();
state.wSocket = client;
client.BeginReceive(state.Buffer,0,ObjectState.BufferSize,0, new AsyncCallback(ReceiveCallback), state);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
private static void ReceiveCallback(IAsyncResult ar)
{
try
{
ObjectState state = (ObjectState)ar.AsyncState;
var client = state.wSocket;
int byteRead = client.EndReceive(ar);
if(byteRead > 0)
{
state.sb.Append(Encoding.ASCII.GetString(state.Buffer, 0, byteRead));
client.BeginReceive(state.Buffer, 0, ObjectState.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
else
{
if(state.sb.Length > 1)
{
response = state.sb.ToString();
}
receiveCompleted.Set();
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
private static void Send(Socket client, string data)
{
byte[] byteData = Encoding.ASCII.GetBytes(data);
client.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallBack), client);
}
private static void SendCallBack(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState;
int byteSent = client.EndSend(ar);
Console.WriteLine($"send: {byteSent} bytes to server");
sendCompleted.Set();
client.DisconnectAsync();
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
private static void ConnectionCallback(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState;
client.EndConnect(ar);
Console.Write($"Socket connection : {client.RemoteEndPoint.ToString()}");
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
static void Main(string[] args)
{
Console.WriteLine("Press any key to contine");
Console.ReadLine();
AsyncSocketClient.StartClient();
Console.ReadLine();
}
}
}
Server console application
that should be taking care about cca 10 clients so thread for everyone is not solution
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Threading;
using System.Net;
namespace AsynchronousServerLearning
{
class Program
{ public class ObjectState
{
public Socket wSocket = null;
public const int bufferSize = 1024;
public byte[] buffer = new byte[bufferSize];
public StringBuilder sb = new StringBuilder();
}
public class AsyncSocketListener
{
public static ManualResetEvent allCompleted = new ManualResetEvent(false);
public static void StartListener()
{
byte[] bytes = new byte[1024];
IPHostEntry ipHost = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ip = ipHost.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ip, 4343);
Socket listener = new Socket(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
try
{
listener.Bind(localEndPoint);
listener.Listen(100);
while(true)
{
allCompleted.Reset();
Console.WriteLine("waiting for incoming connections......");
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
allCompleted.WaitOne();
}
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
Console.WriteLine("Press enter to continue");
Console.ReadLine();
}
private static void AcceptCallback(IAsyncResult ar)
{
allCompleted.Set();
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
ObjectState state = new ObjectState();
state.wSocket = handler;
handler.BeginReceive(state.buffer, 0, ObjectState.bufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
private static void ReadCallback(IAsyncResult ar)
{
string content = String.Empty;
ObjectState state = (ObjectState)ar.AsyncState;
Socket handler = state.wSocket;
int bytesRead = handler.EndReceive(ar);
if(bytesRead > 0)
{
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
content = state.sb.ToString();
if (content.IndexOf("<EOF>", StringComparison.Ordinal) > -1)
{
Console.WriteLine($"Read: {content.Length} bytes from \n socket Data: {content}");
Send(handler,content);
}
else
{
handler.BeginReceive(state.buffer, 0, ObjectState.bufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
}
}
private static void Send(Socket handler, string content)
{
byte[] byteData = Encoding.ASCII.GetBytes(content);
handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
Socket handler = (Socket)ar.AsyncState;
int byteSent = handler.EndSend(ar);
Console.WriteLine($"Sent {byteSent} to client");
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
catch( Exception e)
{
Console.WriteLine(e);
}
}
}
static void Main(string[] args)
{
Console.WriteLine("Press any key to continue");
Console.ReadLine();
AsyncSocketListener.StartListener();
Console.ReadLine();
}
}
}
Log from console:
Press any key to continue
Socket connection : [fe80::3d32:e16b:6438:ad43%8]:4343send: 24 bytes to server
Response received this socket message<EOF>
send: 24 bytes to server
Response received this socket message<EOF>
Socket connection : [fe80::3d32:e16b:6438:ad43%8]:4343System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Net.Sockets.Socket'.
at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult, SocketError& errorCode)
at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult)
at AsynchronousClientLearning.Program.AsyncSocketClient.ReceiveCallback(IAsyncResult ar) in C:\Users\Z660659\source\repos\AsynchronousClientLearning\AsynchronousClientLearning\Program.cs:line 82
...when I try that:
static void Main(string[] args)
{
Console.WriteLine("Press any key to contine");
Console.ReadLine();
AsyncSocketClient.StartClient();
Console.ReadLine();
AsyncSocketClient.StartClient();
Console.ReadLine();
}
I have been looking for answear like 2 hours since I struggle. Now I came with solution that solver the error. With reseting manualReserEvents. If you found something better please let me know.
private static void ReceiveCallback(IAsyncResult ar)
{
try
{
ObjectState state = (ObjectState)ar.AsyncState;
var client = state.wSocket;
int byteRead = client.EndReceive(ar);
if(byteRead > 0)
{
state.sb.Append(Encoding.ASCII.GetString(state.Buffer, 0, byteRead));
client.BeginReceive(state.Buffer, 0, ObjectState.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
else
{
if(state.sb.Length > 1)
{
response = state.sb.ToString();
}
receiveCompleted.Set();
connectComplete.Reset();
receiveCompleted.Reset();
sendCompleted.Reset();
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}

C# UWP TCP Client

I am trying to make a TCP Client in a UWP application.
I can create a client with no issues. The problem is I need to listen continuously to anything that remote device sends back such as a login prompt.
I did try to use Stream Socket also but that listens for incoming only.
The goal is to open a connection and send and receive to that remote device only for the connection.
I have tried many options I have found online with no luck.
Basics of the connection:
Connect to the remote device and stay connected.
Wait for prompts(which can be slow at times).
Send back login in information
Get logged in confirmation
Stay connected and send and receive data continuously.
Any help would be great.
I was able to get it working properly with this:
private TcpClient client;
private NetworkStream recieveData;
private Task rx;
public delegate void DataRecived(string data);
public event DataRecived OnDataRecived;
public delegate void ConnectionStatus(bool data);
public event ConnectionStatus clientConnected;
public delegate void LogStatus(bool data);
public event LogStatus loggedIn;
public delegate void ValueChanged(int value);
public event ValueChanged newLightValue;
public string Ip;
public int Port;
private bool auth;
public bool valueInChanging;
public Client()
{
client = new TcpClient();
rx = new Task(StartReading);
}
public async void Connect()
{
try
{
await client.ConnectAsync(Ip, Port);
clientConnected(client.Connected);
rx.Start();
}
catch (Exception ex)
{
OnDataRecived("Error Connecting" + ex.ToString());
}
}
private void StartReading()
{
while (true)
{
recieveData = client.GetStream();
byte[] bytes = new byte[1024];
Byte[] data = new Byte[256];
string responseData;
if (recieveData != null)
{
int bytesRead = recieveData.Read(bytes, 0, bytes.Length);
responseData = System.Text.Encoding.ASCII.GetString(bytes, 0, bytesRead);
if (!auth)
{
OnReceivedMessage(responseData);
}
else
{
Feedback(responseData);
}
}
}
}

Multi threading with Sockets and passing a string from a class to a form c#

I'm trying to access the string of messageRecieved, which should pass to frmMain.Sort_Data(messageRecived);. However it's null once it hits here. The Console.WriteLine shows the correct data.
public class Client
{
frm_main frmMain = new frm_main();
public string ReturnDat;
//for TCP communications
TcpClient _client = null;
//for sending/receiving data
byte[] data;
public Client(TcpClient client)
{
_client = client;
//start reading data from the client in a separate thread
data = new byte[_client.ReceiveBufferSize];
_client.GetStream().BeginRead(
data, 0, _client.ReceiveBufferSize, receiveMessage, null);
}
public void receiveMessage(IAsyncResult ar)
{
//read from client
int bytesRead;
lock (_client.GetStream())
{
bytesRead = _client.GetStream().EndRead(ar);
}
//if client has disconnected
if (bytesRead < 1)
return;
else
{
//get the message sent
string messageReceived =
ASCIIEncoding.ASCII.GetString(data, 0, bytesRead);
//Console.WriteLine(messageReceived);
frmMain.Sort_Data(messageReceived);
//ReturnDat = messageReceived;
}
//continue reading from client
lock (_client.GetStream())
{
_client.GetStream().BeginRead(
data, 0, _client.ReceiveBufferSize,
receiveMessage, null);
}
}
}
Below is the Sort_Data, which returns nothing when it's hit in the class.
Public void Sort_Data(string data)
{
Messagebox.show(data);
}
Perhaps I'm missing something, or not calling something right?

Transmitting/Sending big packet safely using TcpClient/Socket

I am writing a TCP based client that need to send and receive data. I have used the Asynchronous Programming Model (APM) provided for Socket class by the .NET Framework.
After being connected to the socket, I start wait for data on the socket using BeginReceive.
Now, while I am waiting for the data on the Socket, I may need to send data over the socket. And the send method can be called multiple times,
So i have make sure that
All the bytes from previous Send call is entirely sent.
The way i am sending the Data is safe considering that, while a data send is in progress, any call to send data can be made.
This is my first work on socket, So is my approach right to send data ?
private readonly object writeLock = new object();
public void Send(NetworkCommand cmd)
{
var data = cmd.ToBytesWithLengthPrefix();
ThreadPool.QueueUserWorkItem(AsyncDataSent, data);
}
private int bytesSent;
private void AsyncDataSent(object odata)
{
lock (writeLock)
{
var data = (byte[])odata;
int total = data.Length;
bytesSent = 0;
int buf = Globals.BUFFER_SIZE;
while (bytesSent < total)
{
if (total - bytesSent < Globals.BUFFER_SIZE)
{
buf = total - bytesSent;
}
IAsyncResult ar = socket.BeginSend(data, bytesSent, buf, SocketFlags.None, DataSentCallback, data);
ar.AsyncWaitHandle.WaitOne();
}
}
}
How object is changed into byte[], sometimes the NetworkCommand can be as big as 0.5 MB
public byte[] ToBytesWithLengthPrefix()
{
var stream = new MemoryStream();
try
{
Serializer.SerializeWithLengthPrefix(stream, this, PrefixStyle.Fixed32);
return stream.ToArray();
}
finally
{
stream.Close();
stream.Dispose();
}
}
Complete class
namespace Cybotech.Network
{
public delegate void ConnectedDelegate(IPEndPoint ep);
public delegate void DisconnectedDelegate(IPEndPoint ep);
public delegate void CommandReceivedDelagate(IPEndPoint ep, NetworkCommand cmd);
}
using System;
using System.Net;
using System.Net.Sockets;
using Cybotech.Helper;
using Cybotech.IO;
namespace Cybotech.Network
{
public class ClientState : IDisposable
{
private int _id;
private int _port;
private IPAddress _ip;
private IPEndPoint _endPoint;
private Socket _socket;
private ForwardStream _stream;
private byte[] _buffer;
public ClientState(IPEndPoint endPoint, Socket socket)
{
Init(endPoint, socket);
}
private void Init(IPEndPoint endPoint, Socket socket)
{
_endPoint = endPoint;
_ip = _endPoint.Address;
_port = _endPoint.Port;
_id = endPoint.GetHashCode();
_socket = socket;
_stream = new ForwardStream();
_buffer = new byte[Globals.BUFFER_SIZE];
}
public int Id
{
get { return _id; }
}
public int Port
{
get { return _port; }
}
public IPAddress Ip
{
get { return _ip; }
}
public IPEndPoint EndPoint
{
get { return _endPoint; }
}
public Socket Socket
{
get { return _socket; }
}
public ForwardStream Stream
{
get { return _stream; }
}
public byte[] Buffer
{
get { return _buffer; }
set { _buffer = value; }
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (_stream != null)
{
_stream.Close();
_stream.Dispose();
}
if (_socket != null)
{
_socket.Close();
}
}
}
public void Dispose()
{
Dispose(true);
}
}
}
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using Cybotech.Command;
using Cybotech.Network;
namespace ExamServer.Network
{
public class TcpServer : IDisposable
{
private Socket socket;
private bool secure;
private readonly Dictionary<IPEndPoint, ClientState> clients = new Dictionary<IPEndPoint, ClientState>();
//public events
#region Events
public event CommandDelegate CommandReceived;
public event ConnectedDelegate ClientAdded;
public event DisconnectedDelegate ClientRemoved;
#endregion
//event invokers
#region Event Invoke methods
protected virtual void OnCommandReceived(IPEndPoint ep, NetworkCommand command)
{
CommandDelegate handler = CommandReceived;
if (handler != null) handler(ep, command);
}
protected virtual void OnClientAdded(IPEndPoint ep)
{
ConnectedDelegate handler = ClientAdded;
if (handler != null) handler(ep);
}
protected virtual void OnClientDisconnect(IPEndPoint ep)
{
DisconnectedDelegate handler = ClientRemoved;
if (handler != null) handler(ep);
}
#endregion
//public property
public string CertificatePath { get; set; }
public TcpServer(EndPoint endPoint, bool secure)
{
StartServer(endPoint, secure);
}
public TcpServer(IPAddress ip, int port, bool secure)
{
StartServer(new IPEndPoint(ip, port), secure);
}
public TcpServer(string host, int port, bool secure)
{
StartServer(new IPEndPoint(IPAddress.Parse(host), port), secure);
}
private void StartServer(EndPoint ep, bool ssl)
{
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(ep);
socket.Listen(150);
this.secure = ssl;
socket.BeginAccept(AcceptClientCallback, null);
}
private void AcceptClientCallback(IAsyncResult ar)
{
Socket client = socket.EndAccept(ar);
var ep = (IPEndPoint) client.RemoteEndPoint;
var state = new ClientState(ep, client);
if (secure)
{
//TODO : handle client for ssl authentication
}
//add client to
clients.Add(ep, state);
OnClientAdded(ep);
client.BeginReceive(state.Buffer, 0, state.Buffer.Length, SocketFlags.None, ReceiveDataCallback, state);
//var thread = new Thread(ReceiveDataCallback);
//thread.Start(state);
}
private void ReceiveDataCallback(IAsyncResult ar)
{
ClientState state = (ClientState)ar.AsyncState;
try
{
var bytesRead = state.Socket.EndReceive(ar);
state.Stream.Write(state.Buffer, 0, bytesRead);
// check available commands
while (state.Stream.LengthPrefix > 0)
{
NetworkCommand cmd = NetworkCommand.CreateFromStream(state.Stream);
OnCommandReceived(state.EndPoint, cmd);
}
//start reading data again
state.Socket.BeginReceive(state.Buffer, 0, state.Buffer.Length, SocketFlags.None, ReceiveDataCallback, state);
}
catch (SocketException ex)
{
if (ex.NativeErrorCode.Equals(10054))
{
RemoveClient(state.EndPoint);
}
}
}
private void RemoveClient(IPEndPoint ep)
{
OnClientDisconnect(ep);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
//TODO : dispose all the client related socket stuff
}
}
public void Dispose()
{
Dispose(true);
}
}
}
The same client won't be able to send data to you unless he finishes sending the current bytes.
So on the server side, you will receive the completed data no interrupted by other new messages from that client, but take in consideration that not all the message sent will be received by one hit if it is too big, but still, it is one message in the end after receiving is finished.
As you are using TCP, the network protocol will ensure that packets are received in the same order as sent.
Regarding thread safety it depends a bit on the actual class which you are using for sending. The declaration part is missing in your provided code fragment.
Given by the name you seem to use Socket and this is thread-safe, so every send is actually atomic, if you use any flavor of Stream, then it is not thread-safe and you need some form of synchronization like a lock, which you are currently using anyway.
If you are sending large packets, then it is important to split the receiving and processing part into two different threads. The TCP buffer is actually a lot smaller than one would think and unfortunately it is not covered inside the logs when it is full as the protocol will keep performing resend until everything has been received.

Send a Message Box to a client in my Domain from C# Windows Form

I have got a windows forms project than copying files and folders to clients in my domain. When copying file or copying directory process to [x]clients in my domain. I want to send it a Messagebox that says "There is a new folder or file in your [xdirectory]".
I can't do it by Messenger service because of Messenger service is does not working in XP Sp2 so I need another way for this. Maybe a client/server side application could be make. There will be a listener app in client then I will send it a messagebox.show code then it will show us a messagebox. etc.
I did something similar once before. I got most of this code from somewhere else, but I cannot remember from where.
First the Server Code:
public class HSTcpServer
{
private TcpListener m_listener;
private IPAddress m_address = IPAddress.Any;
private int m_port;
private bool m_listening;
private object m_syncRoot = new object();
public event EventHandler<TcpMessageReceivedEventArgs> MessageReceived;
public HSTcpServer(int port)
{
m_port = port;
}
public IPAddress Address
{
get { return m_address; }
}
public int Port
{
get { return m_port; }
}
public bool Listening
{
get { return m_listening; }
}
public void Listen()
{
try
{
lock (m_syncRoot)
{
m_listener = new TcpListener(m_address, m_port);
// fire up the server
m_listener.Start();
// set listening bit
m_listening = true;
}
// Enter the listening loop.
do
{
Trace.Write("Looking for someone to talk to... ");
// Wait for connection
TcpClient newClient = m_listener.AcceptTcpClient();
//Trace.WriteLine("Connected to new client");
// queue a request to take care of the client
ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessClient), newClient);
}
while (m_listening);
}
catch (SocketException se)
{
Trace.WriteLine("SocketException: " + se.ToString());
}
finally
{
// shut it down
StopListening();
}
}
public void StopListening()
{
if (m_listening)
{
lock (m_syncRoot)
{
// set listening bit
m_listening = false;
// shut it down
m_listener.Stop();
}
}
}
private void sendMessage(string message)
{
// Copy to a temporary variable to be thread-safe.
EventHandler<TcpMessageReceivedEventArgs> messageReceived = MessageReceived;
if (messageReceived != null)
messageReceived(this, new TcpMessageReceivedEventArgs(message));
}
private void ProcessClient(object client)
{
TcpClient newClient = (TcpClient)client;
try
{
// Buffer for reading data
byte[] bytes = new byte[1024];
StringBuilder clientData = new StringBuilder();
// get the stream to talk to the client over
using (NetworkStream ns = newClient.GetStream())
{
// set initial read timeout to 1 minute to allow for connection
ns.ReadTimeout = 60000;
// Loop to receive all the data sent by the client.
int bytesRead = 0;
do
{
// read the data
try
{
bytesRead = ns.Read(bytes, 0, bytes.Length);
if (bytesRead > 0)
{
// Translate data bytes to an ASCII string and append
clientData.Append(Encoding.ASCII.GetString(bytes, 0, bytesRead));
// decrease read timeout to 1 second now that data is
// coming in
ns.ReadTimeout = 1000;
}
}
catch (IOException ioe)
{
// read timed out, all data has been retrieved
Trace.WriteLine("Read timed out: {0}", ioe.ToString());
bytesRead = 0;
}
}
while (bytesRead > 0);
bytes = Encoding.ASCII.GetBytes("clowns");
// Send back a response.
ns.Write(bytes, 0, bytes.Length);
sendMessage(clientData.ToString());
}
}
finally
{
// stop talking to client
if (newClient != null)
newClient.Close();
}
}
}
public class TcpMessageReceivedEventArgs : EventArgs
{
private string m_message;
public TcpMessageReceivedEventArgs(string message)
{
m_message = message;
}
public string Message
{
get
{
return m_message;
}
}
}
The Client Code:
class HSTcpClient
{
private TcpClient _client;
private IPAddress _address;
private int _port;
private IPEndPoint _endPoint;
private bool _disposed;
public HSTcpClient(IPAddress address, int port)
{
_address = address;
_port = port;
_endPoint = new IPEndPoint(_address, _port);
}
public void SendForwardedClientMessage(int senderId, int receiverId, int hsId)
{
SendMessage(senderId.ToString() + ":" + receiverId.ToString() + ":" + hsId.ToString());
}
public void SendUpdatedCGBMessage()
{
SendMessage("Update your CGB you clowns");
}
public void SendMessage(string msg)
{
try
{
_client = new TcpClient();
_client.Connect(_endPoint);
// Get the bytes to send for the message
byte[] bytes = Encoding.ASCII.GetBytes(msg);
// Get the stream to talk to the server on
using (NetworkStream ns = _client.GetStream())
{
// Send message
Trace.WriteLine("Sending message to server: " + msg);
ns.Write(bytes, 0, bytes.Length);
// Get the response
// Buffer to store the response bytes
bytes = new byte[1024];
// Display the response
int bytesRead = ns.Read(bytes, 0, bytes.Length);
string serverResponse = Encoding.ASCII.GetString(bytes, 0, bytesRead);
Trace.WriteLine("Server said: " + serverResponse);
}
}
catch (SocketException se)
{
Trace.WriteLine("There was an error talking to the server: " +
se.ToString());
}
finally
{
Dispose();
}
}
#region IDisposable Members
public void Dispose()
{
Dispose(true);
System.GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
if (_client != null)
_client.Close();
}
_disposed = true;
}
}
#endregion
}
Then to use, create a server variable in your form code:
private HSTcpServer m_server;
and I created a background worker thread:
private System.ComponentModel.BackgroundWorker hsTcpServerThread;
handled the DoWork event:
private void hsTcpServerThread_DoWork(object sender, DoWorkEventArgs e)
{
m_server = new HSTcpServer(<pick your port>);
m_server.MessageReceived += new EventHandler<TcpMessageReceivedEventArgs>(m_server_MessageReceived);
m_server.Listen();
}
Then handle the message recieved event:
void m_server_MessageReceived(object sender, TcpMessageReceivedEventArgs e)
{
//<your code here> - e contains message details
}
Then to send a message to the server:
HSTcpClient client = new HSTcpClient(<ip address>, <port you picked>);
client.SendForwardedClientMessage(<message details>);
Hopefully I got everything in there.
You can use the FileSystemWatcher in the client. That way you do not have to deal with remoting or listening on ports.
If you really want to communicate between the two machines you can do using remoting, or via the TcpListener.

Categories

Resources