I have a c# winform app.
I also have a c# DLL.
The DLL is compiled in 32bit format.
The GUI is compiled using 64bit format.
I am using pipes to faciliatte messagubng between the 2 different compilations.
The DLL (client) sends to my GUI (Server) a byte array image.
This is my code for the server:
public partial class Form1 : Form
{
public delegate void NewMessageDelegate(System.Drawing.Bitmap NewMessage);
private PipeServer pipeName;
public Form1()
{
InitializeComponent();
pipeName = new PipeServer();
pipeName.PipeMessage += new DelegateMessage(PipesMessageHandler);
}
private void cmdListen_Click(object sender, EventArgs e)
{
try
{
pipeName.Listen("TestPipe");
txtMessage.Text = "Listening - OK";
cmdListen.Enabled = false;
}
catch (Exception)
{
txtMessage.Text = "Error Listening";
}
}
private void PipesMessageHandler(System.Drawing.Bitmap message)
{
try
{
if (this.InvokeRequired)
{
pictureBox1.Invoke((MethodInvoker)(() => pictureBox1.Image = message));
}
else
{
pictureBox1.Image = message;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
}
So, the User will press my 'cmdListen' button.
This is my client code (in the DLL):
class PipeClient
{
public void Send(Bitmap frame, string PipeName, int TimeOut = 1000)
{
try
{
NamedPipeClientStream pipeStream = new NamedPipeClientStream(".", PipeName, PipeDirection.Out, PipeOptions.Asynchronous);
pipeStream.Connect(TimeOut);
Debug.WriteLine("[Client] Pipe connection established");
byte[] _buffer = null;
using (var ms = new MemoryStream())
{
frame.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
_buffer = ms.ToArray();
}
pipeStream.BeginWrite(_buffer, 0, _buffer.Length, AsyncSend, pipeStream);
}
catch (TimeoutException oEX)
{
Debug.WriteLine(oEX.Message);
}
}
private void AsyncSend(IAsyncResult iar)
{
try
{
// Get the pipe
NamedPipeClientStream pipeStream = (NamedPipeClientStream)iar.AsyncState;
// End the write
pipeStream.EndWrite(iar);
pipeStream.Flush();
pipeStream.Close();
pipeStream.Dispose();
}
catch (Exception oEX)
{
Debug.WriteLine(oEX.Message);
}
}
}
The 'Send' is called by a timer in my DLL to 'pump' images to my GUI app.
This all works.
What I need to add/do is to pass some parameters from server(GUI) to my DLL(client) BEFORE the timer is triggered.
So, in my client DLL I would have this function (eg)
public void InitDLL(object[] args)
{
//do something with these parameters
//start timer off
}
So, how can I call this function from my GUI using Pipes?
I have noticed that the PipeDirection can be set to be InOut. But I am unsure how to simply add some code to my server app to send a message to my client.
Related
I have a C# application which accepts data from a port(9100 ie, uses data when printer print something) and use it into an application. The problem is, sometimes it doesn't receiving data completely from printer and I have seen some questions regarding the difficulties in reading data at one time in TCP.
As I am not familiar with this, somebody please suggest me a better way to fix it.
Thanks in advance..
Here is my code
TcpListener Listener = null;
public Thread T = null;
public FeederControlMonitor()
{
InitializeComponent();
}
private void FeederControlMonitor_Load(object sender, EventArgs e)
{
txtStatus.Text = "Feeder waiting for data...";
ThreadStart Ts = new ThreadStart(StartReceiving);
T = new Thread(Ts);
T.Start();
}
public void StartReceiving()
{
ReceiveTCP(9100);
}
public void ReceiveTCP(int portN)
{
try
{
Listener = new TcpListener(IPAddress.Any, portN);
Listener.Start();
}
catch (Exception ex)
{
File.WriteAllText(#"C:\\Drive\\ex.txt", ex.Message);
Console.WriteLine(ex.Message);
}
try
{
while (true)
{
Socket client = Listener.AcceptSocket();
var childSocketThread = new Thread(() =>
{
byte[] data = new byte[20000];
int size = client.Receive(data);
ParseData(System.Text.Encoding.Default.GetString(data));
//Here some process will do with received data
client.Close();
});
childSocketThread.IsBackground = true;
childSocketThread.Start();
}
Listener.Stop();
}
catch (Exception ex)
{
File.WriteAllText(#"C:\\ex.txt", ex.Message);
}
}
My client/server programs work well with each other, but only when the server is up and running before my client starts. If the client fails to connect on the first try, I can't get it to try again.
Here's my Client's connect method.
public void connect()
{
IPAddress server_address = IPAddress.Parse("127.0.0.1");
IPEndPoint server_ip = new IPEndPoint(server_address, 5685);
Console.WriteLine("2");
bool connected = false;
while (!connected)
{
try
{
Console.WriteLine("IN CONNECTED");
udp_client.Connect(server_ip);
byte[] send_data = Encoding.ASCII.GetBytes("INIT");
udp_client.Send(send_data, send_data.Length);
byte[] received_bytes = udp_client.Receive(ref server_ip);
string received_data = Encoding.ASCII.GetString(received_bytes);
if (received_data == "INIT")
{
connected = true;
Console.WriteLine("RECEIVED INIT");
listen(server_ip);
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
What I was hoping to see is the udp_client.Connect(server_ip) to loop until I received that "INIT" message from the server.
As it currently stands, there is no loop. It seems to get stuck on udp_client.Receive(ref server_ip).
Any help would be appreciated!
This is pseudoCode - you will have to move somethings to class scope to allow future send/receives (which you'd do using a different method). This is only designed to show you how to connect when the connection blocks:
bool isClientConnected = false;
var connector = new System.ComponentModel.BackgroundWorker();
public void connectToUDP(){
connector.DoWork+= connect;
connector.RunWorkerAsync();
}
private void connect(object sender, DoWorkEventArgs e)
{
IPAddress server_address = IPAddress.Parse("127.0.0.1");
IPEndPoint server_ip = new IPEndPoint(server_address, 5685);
Console.WriteLine("2");
try
{
Console.WriteLine("Waiting for server...");
udp_client.Connect(server_ip);
byte[] send_data = Encoding.ASCII.GetBytes("INIT");
udp_client.Send(send_data, send_data.Length);
byte[] received_bytes = udp_client.Receive(ref server_ip);
string received_data = Encoding.ASCII.GetString(received_bytes);
if (received_data == "INIT")
{
isClietConnected = true;
Console.WriteLine("now connected");
listen(server_ip);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
public bool sendReceiveUDP(string send){
if(!isClientConnected){
return false;
}
//perform send
return true;
}
You would then maintain the connected session using class scope and send/receive using a different method. This is for connect only since you only need to do it once.
How you set something like this up:
private bool isConnected = false();
private bool send(){
if(!isConnected){
connect();
}
//send
}
private bool connect(){
if(!isConnected){
//launch connection thread
}
}
private delegate void onNewReceive(string message);
public event onNewReceive onNewReceiveEvent;
public void fireEvent(string message){
onNewReceiveEvent.Invoke(message);
}
private void waitForData(object sender, DoWorkEventArgs e){
//this is the backgroundworker
while(true){
receive();
fireEvent(message);
}
}
Then, subscribe to the onNewREceivedEvent in another class and process the inbound message. onNewReceivedEvent += processInboundMEsasage();
This is all psuedocode and "brain compiled" (creit to others) so it's only meant for demonstrations. Without intellisense, I'm lost.
I am reading from a Ethernet port using the following code:
System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient();
class ClsReadPort
{
public void Connect()
{
try
{
clientSocket = new System.Net.Sockets.TcpClient();
if (!clientSocket.Connected)
{
clientSocket.Connect("192.168.0.25", 1324);
}
}
catch (Exception ex)
{
MsgBox(ex.Message)
}
}
public string Capture()
{
try
{
if (clientSocket.Connected)
{
NetworkStream serverStream = clientSocket.GetStream();
byte[] inStream = new byte[clientSocket.ReceiveBufferSize + 1];
serverStream.Read(inStream, 0, Convert.ToInt32(clientSocket.ReceiveBufferSize));
string returndata = System.Text.Encoding.ASCII.GetString(inStream);
oCapture = returndata;
}
}
}
catch (Exception ex)
{
MsgBox(ex.Message)
}
}
}
In my main program for updating the reading values:
ClsReadPort objRead = new ClsReadPort();
private void timer1_Tick(object sender, EventArgs e)
{
txtReadValue.Value = objRead.Capture();
}
It is working fine. But when ever the Ethernet cable disconnects, the entire UI gets hanged. Its stays on this line:
serverStream.Read(inStream, 0, Convert.ToInt32(clientSocket.ReceiveBufferSize));
How to do it as parallel task without affecting the UI??
In .net 4.5 you could use the async methods and await them
For Async have a look here
Here is a also a Async Socket Sample without await form MSDN
You can use Dispatcher to start your Capture task in separate thread
Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
try
{
txtReadValue.Value = objRead.Capture();
}
catch { }
}
I am currently tyring to create a Multi threading and async tcp server that implements the Tcpl listener
Current the server is working as intended as i am able to send data to the server an transmit data to the client with out any problems
However after i have sent data to the server and then sent data back to the client, when the client sends data back to the server again the server is unabe to pick up the data
I have tried for days to find an answer to this problem however with no luck
Here is the code that i am currently using in the server:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows.Forms;
using System.IO;
namespace MyTcpAsyncClass
{
public class StateObject
{
public TcpClient MyTcpClient = null;
public NetworkStream MyNetworkStream = null;
public const int MyBufferSize = 1024;
public byte[] MyBuffer = new byte[MyBufferSize];
public string RequestString = "";
public StringBuilder MyStringBuilder = new StringBuilder();
char[] RequestChars; // Char array of Request
const char STX = (char)0x02; // Start Character
const char FTX = (char)0x03; // Finish Character
public void Dispose()
{
try
{
MyTcpClient.Close();
MyNetworkStream.Close();
MyNetworkStream.Dispose();
}
catch (Exception ex)
{
MessageBox.Show("Message:\n" + ex.Message + "\n\nStacktrace:\n" + ex.StackTrace);
}
}
}
public static class AsyncServerFunctions
{
private static int mPort = 0;
private static ManualResetEvent MyManualResetEvent = new ManualResetEvent(false);
public static void StartListening()
{
//Catch to Tcp Client Connection
try
{
//Get the database connection
//MyReaderWriterLockSlim.EnterReadLock();
LoadSettings();
//MyReaderWriterLockSlim.ExitReadLock();
TcpListener MyTcpListener = new TcpListener(IPAddress.Any, mPort);
MyTcpListener.Start();
while (true)
{
//Set the event to nonsignaled state
MyManualResetEvent.Reset();
//Start an asynchronous TcpListener to listen for a connection
MyTcpListener.BeginAcceptTcpClient(AcceptTcpClientCallback, MyTcpListener);
//Wait until a connection is made before continuing
MyManualResetEvent.WaitOne();
}
MyTcpListener.Stop();
}
catch (Exception ex)
{
AddErrorLog(ex.Message, ex.StackTrace);
}
}
private static void AcceptTcpClientCallback(IAsyncResult result)
{
try
{
//BeginAcceptTcpClientCallback
//Signal the main thread to continue
MyManualResetEvent.Set();
//Get the TcpClientNetworkStream:
TcpListener MyTcpListener = (TcpListener)result.AsyncState;
//Finish Async Get Client Process
TcpClient MyTcpClient = MyTcpListener.EndAcceptTcpClient(result);
StateObject MyStateObject = new StateObject();
MyStateObject.MyTcpClient = MyTcpClient;
MyStateObject.MyNetworkStream = MyTcpClient.GetStream();
//Begin Async read from the NetworkStream
MyStateObject.MyNetworkStream.BeginRead(MyStateObject.MyBuffer, 0, StateObject.MyBufferSize, new AsyncCallback(BeginReadCallback), MyStateObject);
}
catch (Exception ex)
{
AddErrorLog(ex.Message, ex.StackTrace);
}
}
private static void BeginReadCallback(IAsyncResult result)
{
StateObject MyStateObject = (StateObject)result.AsyncState;
NetworkStream MyNetworkStream = MyStateObject.MyNetworkStream;
string MyRequestString = "";
try
{
//Get Request Data here
if (MyStateObject.MyBuffer.Length > 0)
{
//Store the data recived
MyStateObject.MyStringBuilder.Clear();
MyStateObject.MyStringBuilder.Append(Encoding.ASCII.GetString(MyStateObject.MyBuffer));
//Get the stored Request string
MyRequestString = MyStateObject.MyStringBuilder.ToString();
//Record the string recived
DatabaseFunctions.AddMessageLog("String Recived (BeginReadCallback): " + MyRequestString);
//Remove the first and last character
MyRequestString = CleanString(MyRequestString);
//Record the Request String
DatabaseFunctions.AddMessageLog("Request String Recived:" + MyRequestString);
//Get the Message Identifier
string MessageIdentifier = "";
MessageIdentifier = MyRequestString.Substring(0, 2);
switch (MessageIdentifier)
{
case "value":
SendResponse(MyStateObject, StartUp(MessageIdentifier, MyRequestString));
SendResponse(MyStateObject, SendTransactionStart(MessageIdentifier, MyAmount));
GetResponse(MyStateObject);
break;
default:
//***Default Case***
SendResponse(MyStateObject, DefaultCase(MyRequestString));
break;
}
//Dispose of the connection
MyStateObject.Dispose();
}
}
catch (Exception ex)
{
AddErrorLog(ex.Message, ex.StackTrace);
try
{
MyStateObject.Dispose();
}
catch
{
AddErrorLog(ex.Message, ex.StackTrace);
}
}
}
private static void SendResponse(StateObject pMyStateObject, string pResponseString)
{
try
{
//Send a response to the client
//Get bytes from string sent
byte[] MyResponseBytes = Encoding.ASCII.GetBytes(pResponseString);
//Get the network stream
NetworkStream MyNetworkStream = pMyStateObject.MyNetworkStream;
//Call SendResponseCallback
MyNetworkStream.BeginWrite(MyResponseBytes, 0, MyResponseBytes.Length, new AsyncCallback(SendResponseCallback), pMyStateObject);
}
catch (Exception ex)
{
AddErrorLog(ex.Message, ex.StackTrace);
}
}
private static void GetResponse(StateObject pStateObject)
{
//This will run a new AsyncCallback To get the response from the client
NetworkStream MyNetworkStream = pStateObject.MyNetworkStream;
pStateObject.MyBuffer = new byte[1024];
MyNetworkStream.BeginRead(pStateObject.MyBuffer, 0, pStateObject.MyBuffer.Length, new AsyncCallback(BeginReadCallback), pStateObject);
}
private static void SendResponseCallback(IAsyncResult result)
{
try
{
//End the send procedure
StateObject MyStateObject = (StateObject)result.AsyncState;
NetworkStream MyNetworkStream = MyStateObject.MyNetworkStream;
MyNetworkStream.Flush();
}
catch (Exception ex)
{
AddErrorLog(ex.Message, ex.StackTrace)
}
}
private static void ShowExceptionMessage(string pMessage, string pStacktrace)
{
MessageBox.Show("Message:\n" + pMessage + "\n\nStacktrace:\n" + pStacktrace);
}
private static void AddErrorLog(string pMessage, string pStackTrace)
{
DatabaseFunctions.AddMessageLog("Message:" + pMessage + "; Stacktrace:" + pStackTrace);
}
}
}
Thanks All
You should call BeginAcceptTcpClient in AcceptTcpClientCallback also. You don't accept any new connection after the first one.
In your BeginReadCallback function you dispose off the object you have used to invoke BeginRead try running the code without dispose function and you are only calling the GetRespone function in switch condition, try calling BeginRead in your BeginReadCallback function.
So, I have a board game that uses Asynchronous socket to operate over LAN. The thing is, I have little to no understanding of Asynchronous socket programming, or of threads, but I do my best to try.
I based my program off a chat program, so I use that part to send multiple strings.
So, here's part of the code for the Client:
private void Connect(IAsyncResult iar)
{
try
{
Socket client_conn = (Socket)iar.AsyncState;
client_conn.EndConnect(iar);
g_bmsg = new byte[1024];
check = true;
string szData = "#Player " + lblName.Text + " connected.";
sendingFunction(szData);
g_client_conn.BeginReceive(g_bmsg, 0, g_bmsg.Length, SocketFlags.None, new AsyncCallback(Receive), g_client_conn);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "GG");
}
}
private void Send(IAsyncResult iar)
{
Socket client_conn = (Socket)iar.AsyncState;
client_conn.EndSend(iar);
}
private void Receive(IAsyncResult iar)
{
if (g_bmsg.Length != 0)
{
SetLabelText(Encoding.ASCII.GetString(g_bmsg, 0, g_bmsg.Length));
check = false;
}
}
private void SetLabelText(string txt)
{
if (lblBuffer.InvokeRequired)
lblBuffer.Invoke(new MethodInvoker(delegate { SetLabelText(txt); }));
else
{
lblBuffer.Text = txt;
}
if (lblBuffer.Text.StartsWith("#"))
{
lblStatmsg.Text = lblBuffer.Text.Replace("#", "");
}
if (lblBuffer.Text.StartsWith("$"))
{
lblStatmsg.Text = "Server Settings Received.";
lblBuffer.Text = lblBuffer.Text.Replace("$", "");
option_Postn = int.Parse(lblBuffer.Text.Substring(0, 1));
option_First = int.Parse(lblBuffer.Text.Substring(2, 1));
}
if (lblBuffer.Text.StartsWith("#"))
{
MessageBox.Show(lblBuffer.Text);
}
}
And here's part of the code for the Server:
private void Accept(IAsyncResult iar)
{
Socket server_conn = (Socket)iar.AsyncState;
g_server_conn = server_conn.EndAccept(iar);
g_bmsg = new byte[1024];
check = true;
g_server_conn.BeginReceive(g_bmsg, 0, g_bmsg.Length, SocketFlags.None, new AsyncCallback(Recieve), g_server_conn);
}
private void Send(IAsyncResult iar)
{
Socket server_conn = (Socket)iar.AsyncState;
server_conn.EndSend(iar);
}
private void Recieve(IAsyncResult iar)
{
try
{
Socket server_conn = (Socket)iar.AsyncState;
server_conn.EndReceive(iar);
if (g_bmsg.Length != 0)
{
SetLabelText(Encoding.ASCII.GetString(g_bmsg, 0, g_bmsg.Length));
check = false;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "GG");
}
}
private void SetLabelText(string txt)
{
if (lblBuffer.InvokeRequired)
lblBuffer.Invoke(new MethodInvoker(delegate { SetLabelText(txt); }));
else
{
lblBuffer.Text = txt;
}
if (lblBuffer.Text.StartsWith("#"))
{
lblStatmsg.Text = lblBuffer.Text.Replace("#", "");
}
else if (lblBuffer.Text.StartsWith("#"))
{
MessageBox.Show(lblBuffer.Text);
}
else if (lblBuffer.Text.StartsWith("%"))
{
}
}
Basically, since the game sends more than messages (it can send settings, or game pieces, etc), I ran the sender function everytime I need to send something, and on the other side, the Receiver decodes the string sent based on the first character (# means the string is a setting, for example).
The problem is, after the first time both host and client sent something to one another, they can't seem to send again. No error, no message, no nothing. Just won't send. Is there something wrong with the sendingFunction? Or perhaps the delegate something? I don't know. Some advice would be appreciated, guys. And thanks in advance.
You're never calling BeginReceive again. The typical practice in async socket programming is to process the received data, then call BeginReceive again so that you can then process the next bit of data that comes in.