Unsolvable reason behind Connection Timeout - c#

Server Code
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Runtime.Serialization.Formatters.Binary;
using Global;
using System.IO;
namespace Server
{
class Program
{
static List<string> BlackList = new List<string>();
static List<TcpClient> Clients = new List<TcpClient>();
static object _lock = new object();
static BinaryFormatter Formatter = new BinaryFormatter();
static TcpListener Server;
static void Main(string[] args)
{
Init();
Console.ReadLine();
}
/*
* Initiate the server and start listening
*/
static void Init()
{
Server = new TcpListener(IPAddress.Any, 7777);
Server.Start();
Task.Factory.StartNew(() => Listen());
}
/*
* Listens to new incoming connections
* Assigns the new client a worker who will listen to it's requests
* Add the client to the list of active clients
*/
static void Listen()
{
for (;;)
{
TcpClient client = Server.AcceptTcpClient();
lock(_lock)
Clients.Add(client);
Task.Factory.StartNew(() => Work(client));
Thread.Sleep(100);
}
}
/*
* Listens to incoming requests from a client and sends a response back if necessary
* On disconnect remove client from active clients list
*/
static void Work(TcpClient client)
{
while (client.Connected)
{
NetworkStream stream = client.GetStream();
try
{
dynamic request = Formatter.Deserialize(stream);
Response response = HandleRequest(request);
if(response != null)
Formatter.Serialize(stream, response);
}
catch(Exception ex)
{
Console.Write(ex.Message);
}
}
lock (_lock)
Clients.Remove(client);
}
/*
* Handles File Transfer Requests
*/
static Response HandleRequest(FileTransferRequest request)
{
string file = request.File;
FileTransferResponse response;
if (File.Exists($"{Environment.CurrentDirectory}\\{file}"))
response = new FileTransferResponse(File.ReadAllBytes(file));
else
response = new FileTransferResponse(null);
return response;
}
}
}
Client Code
using System;
using System.Net.Sockets;
using System.Runtime.Serialization.Formatters.Binary;
using Global;
using System.IO;
namespace Client
{
class Program
{
static TcpClient Server;
static void Main(string[] args)
{
string file = args[0];
string output = args[1];
Init();
NetworkStream stream = Server.GetStream();
BinaryFormatter formatter = new BinaryFormatter();
//Request
FileTransferRequest request = new FileTransferRequest(file);
formatter.Serialize(stream, request);
//Get Response
FileTransferResponse response = (FileTransferResponse) formatter.Deserialize(stream);
if (response.File == null)
Console.Write("File not found");
else
{
File.WriteAllBytes(output, response.File);
Console.Write("Success");
}
Console.ReadLine();
}
static void Init()
{
try
{
Server = new TcpClient("lordfrostbyte.webhop.me", 7777);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.ReadLine();
Environment.Exit(-1);
}
}
}
}
Global Library Code
namespace Global
{
[Serializable]
public abstract class Request
{
}
[Serializable]
public class FileTransferRequest : Request
{
public string File;
public FileTransferRequest(string File)
{
this.File = File;
}
}
[Serializable]
public abstract class Response
{
}
[Serializable]
public class FileTransferResponse : Response
{
public byte[] File;
public FileTransferResponse(byte[] File)
{
this.File = File;
}
}
}
This is my code... It's not working !
But I have configured port forwarding
I have also disabled my firewall
My guess is something is wrong with windows. However I do not want to format my computer in order to solve this. I would much appreciate any input that would lead to solving this issue. I have had this issue for a while and I was wondering if anyone else has had a similar issue and if anyone has ever solved this. At the moment I have no clue how to even troubleshoot this issue. Do note that if I host the server on LAN and connect to LAN it works perfectly.

I had to reinstall pcap drivers.

Related

Multi-threaded Named Pipe Server

I'm trying to create a Multi-Threaded Named Pipe Server which can handle multiple requests in parallel. See below for my code.
The behaviour is not as expected. If new requests come in while the current one is busy it throws "access to the path is denied" error until the current executing thread is released.
Any idea what could be the problem ?
using Newtonsoft.Json;
using System;
using System.IO;
using System.IO.Pipes;
using System.Security.AccessControl;
using System.Security.Principal;
using System.Text;
using System.Threading;
namespace API.PipeServer
{
public class Server
{
private bool running;
private Thread runningThread;
private EventWaitHandle terminateHandle = new EventWaitHandle(false, EventResetMode.AutoReset);
public string PipeName { get; set; }
private void ServerLoop()
{
while (running)
{
ProcessNextClient();
}
terminateHandle.Set();
}
public void Run()
{
running = true;
runningThread = new Thread(ServerLoop);
runningThread.Start();
}
public void Stop()
{
running = false;
terminateHandle.WaitOne();
}
public virtual string ProcessRequest(string message)
{
return "";
}
public void ProcessClientThread(object o)
{
using (NamedPipeServerStream pipeStream = (NamedPipeServerStream)o)
{
StreamReader sr = new StreamReader(pipeStream);
//Receive instruction message
string instructionJson = sr.ReadLine();
Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}: --- Receiving Instruction ---");
Console.WriteLine(instructionJson);
//Getting instruction message
var instruction = JsonConvert.DeserializeObject<InstructionHandler.Instruction>(instructionJson);
//Get data
var json = API.API.GetAPIJson(instruction);
//Send data back to Python client
try
{
pipeStream.Write(Encoding.UTF8.GetBytes(json));
pipeStream.WaitForPipeDrain();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}: --- Closing Stream ---");
pipeStream.Close();
pipeStream.Dispose();
}
}
public void ProcessNextClient()
{
try
{
Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}: Creating server");
PipeSecurity pipeSecurity = new PipeSecurity();
pipeSecurity.AddAccessRule(new PipeAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), PipeAccessRights.ReadWrite, AccessControlType.Allow));
var pipeStream = NamedPipeServerStreamAcl.Create("test_api", PipeDirection.InOut, 254, PipeTransmissionMode.Message, PipeOptions.None, 1024, 1024, pipeSecurity);
pipeStream.WaitForConnection();
//Spawn a new thread for each request and continue waiting
Thread t = new Thread(ProcessClientThread);
t.Start(pipeStream);
}
catch (Exception e)
{
Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}: Error - {e.Message}");
}
}
}
}
Below is a typical output:

WiFi communication between C# and ESP8266 [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I'm working on school project right now and I'm looking for the simplest way to connect C# with ESP8266 not via SerialPort (COM4) but via WiFi module on ESP8266 (I have to use this method). I have to build simple project to sending measured data from ESP to C# and also receiving my own defined control commands (strings like "LEDON" "LEDOFF" etc.) from C# to ESP just like remote control of measurement project. I have low knowledge in C# same as basics of servers/internet and things like that. I have everything done in Arduino IDE code but I'm stuck on C# cause I never before programmed there. I hope you understand my bad English and concept of my question. :)
EDIT:
Well, so I did some changes in my school project and now I am on this stage, where I need to solve this part of code. I hope that is last step to finish my project. All I have to do is solve Writing data from C# to ESP using unfilled method named "Writing" in following code:
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace ESP8266
{
public class Projekt
{
public event MessageEventHandler Message;
public delegate void MessageEventHandler(Projekt sender, string Data);
public TcpListener server;
public Thread W_Thread;
public Thread R_Thread;
public bool IsLiserning = true;
public TcpClient client;
public StreamReader clientdata;
public StreamWriter serverdata;
public Projekt()
{
server = new TcpListener(IPAddress.Parse(Dns.GetHostEntry(Dns.GetHostName().ToString()).AddressList[1].ToString()), 5000);
server.Start();
W_Thread = new Thread(new ThreadStart(Writing));
W_Thread.Start();
R_Thread = new Thread(new ThreadStart(Reading));
R_Thread.Start();
}
public void Reading()
{
while (IsLiserning == true)
{
if (server.Pending() == true)
{
client = server.AcceptTcpClient();
clientdata = new StreamReader(client.GetStream());
}
try
{
Message?.Invoke(this, clientdata.ReadLine());
}
catch (Exception){}
}
}
public void Writing()
{
while (IsLiserning == true)
{
if (server.Pending() == true)
{
client = server.AcceptTcpClient();
serverdata = new StreamWriter(client.GetStream());
}
try
{
//NEED_TO_SOLVE_THIS_PART
}
catch (Exception){}
}
}
}
}
Maybe there is missing something more than that part of code and you guys are able to help me I hope :) Thanks for all answers by the way :)
You may look at this project, basically you want to communicate via TCP/IP between the arduino and the C#. consider the C# as the server and the arduino as the client. Then they just need to send message to each other to communicate.
The link I'm providing is doing a lot more than needed, so if you're lost, maybe start with something really basic and look here and check the links at the end talking about c# server. They will be easier to understand compared to my first link.
[EDIT] Ok, only links answer is dangerous and not the best, so here is a really light version of what I gave through the first link:
Your server will have a list of receivers, each receiver only handle one client. It's a big simplification of one of my project, I hope that by removing lots of things I didn't break anything:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Windows.Data;
namespace DemoServer.Models
{
public class Server
{
public TcpListener Listener { get; set; }
public int Port { get; set; }
public bool IsStarted { get; private set; }
public List<Receiver> Receivers = new List<Receiver>();
public Server(int port)
{
Receivers.Clear();
BindingOperations.EnableCollectionSynchronization(Receivers, Receivers);
Port = port;
IsStarted = false;
}
public void Start()
{
if (!IsStarted)
{
try
{
Listener = new TcpListener(System.Net.IPAddress.Any, 0);
Listener.Start();
IsStarted = true;
IPAddress address = ((IPEndPoint)Listener.LocalEndpoint).Address;
int port = ((IPEndPoint) Listener.LocalEndpoint).Port;
Console.WriteLine("Server Started");
//Start Async pattern for accepting new connections
WaitForConnection();
}
catch (Exception e)
{
Console.WriteLine(e);
IsStarted = false;
}
}
}
public void Stop()
{
if (IsStarted)
{
Listener.Stop();
IsStarted = false;
Receivers.Clear();
Console.WriteLine("Server Stopped");
}
}
private void WaitForConnection()
{
Listener.BeginAcceptTcpClient(new AsyncCallback(ConnectionHandler), null);
}
private void ConnectionHandler(IAsyncResult ar)
{
if (IsStarted)
{
Receiver newClient = new Receiver(Listener.EndAcceptTcpClient(ar), this);
newClient.Start();
Receivers.Add(newClient);
WaitForConnection();
}
}
public void SomeInteractionBetweenClients()
{
Console.WriteLine("Interaction!");
}
}
}
Then comes the Receiver code, where you really handle the communication with your client:
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Sockets;
using System.Threading;
namespace DemoServer.Models
{
public class Receiver : ModelBase
{
bool ConnectionStatus = false;
private uint m_Id = 0;
public uint Id
{
get { return m_Id; }
set => SetAndRaisePropertyChanged(ref m_Id, value);
}
private Thread receivingThread;
private Thread sendingThread;
public Server Server { get; set; }
public TcpClient Client { get; set; }
public List<String> MessageQueue { get; private set; }
public Receiver(TcpClient client, Server server)
{
MessageQueue = new List<String>();
Server = server;
Client = client;
Client.ReceiveBufferSize = 1024;
Client.SendBufferSize = 1024;
ConnectionStatus = true;
}
public void Start()
{
receivingThread = new Thread(ReceivingMethod);
receivingThread.IsBackground = true;
receivingThread.Start();
sendingThread = new Thread(SendingMethod);
sendingThread.IsBackground = true;
sendingThread.Start();
}
private void Disconnect()
{
if (!ConnectionStatus) return;
ConnectionStatus = false;
Client.Client.Disconnect(false);
Client.Close();
}
private void SendingMethod()
{
while (ConnectionStatus)
{
if (MessageQueue.Count > 0)
{
var message = MessageQueue[0];
try
{
NetworkStream clientStream = Client.GetStream();
StreamWriter streamWriter = new StreamWriter(clientStream);
streamWriter.Write(message);
streamWriter.Flush();
Console.WriteLine($"We are sending '{message}' to the client");
}
catch
{
Disconnect();
}
finally
{
MessageQueue.RemoveAt(0);
}
}
Thread.Sleep(30);
}
}
private void ReceivingMethod()
{
while (ConnectionStatus)
{
if (Client.Available > 0)
{
try
{
NetworkStream clientStream = Client.GetStream();
StreamReader streamReader = new StreamReader(clientStream);
char[] puchBuffer = new char[Client.Available];
int iQtt = streamReader.Read(puchBuffer, 0, Client.Available);
string msg = String.Empty;
for (int i = 0; i < puchBuffer.Length; i++)
{
msg = $"{msg}{Convert.ToString(puchBuffer[i])}";
}
OnMessageReceived(msg);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
Thread.Sleep(30);
}
}
private void OnMessageReceived(String msg)
{
// Here you can parse the messages coming ffrom the client and do whatever is needed
// If needed, you can even call some public methods from the server to forward some info to an other client for example or just the server:
// eg: Server.SomeInteractionBetweenClients();
}
}
}
I hope this will help for the communication part. For the GUI there are lots of tutorials on the web but if possible I still think WPF/MVVM is better to learn than winforms.
From my understanding your project requires 2 way communication. Making c# as server will not be ideal since there is no easy way to send command from C# to esp8266. I assume your project is utilizing esp8266 as the arduino platform (not attaching esp8266 to arduino as wifi module), please check out MQTT which is a broker for publishing and subscribing messages. That way both esp8266 and C# code and communicate via MQTT and achieve 2 way communication purpose.
for esp8266, you can check out arduino MQTT library for esp8266 here: https://github.com/knolleary/pubsubclient.

C# Sending value from WebSocket Server Thread to Main()

I am trying to write a program to control home automation devices. This involves a WebSocket server that runs infinitely in a background thread listening for clients. The client sends JSON packets that contain settings. When the server gets a JSON packet, I want it to read and change any settings as needed in the Main()
I have a working WebSocket server and I have tried to use the PropertyChangedEvent but it never seems to see the handler. I suspect this occurs because they exist in different threads.
I have attached my code below as well as the example I have been working off of. There is a chance I am way off the mark here but this is the best I could find with the reading I have been doing.
Any help would be appreciated!
This is the Main():
using System;
using System.Threading;
using System.ComponentModel;
namespace HomeAutomation
{
class Controller
{
static void Main(string[] args)
{
bool passGo = false;
Thread SocketThread = new Thread(Socket.WebSocketServer);
SocketThread.IsBackground = true;
SocketThread.Start();
//This line lets the user know the Socket Thread is running in the background
Console.WriteLine("Socket Thread is running in the background: {0}", SocketThread.IsBackground);
do {
char input = Console.ReadKey().KeyChar;
if (input == 'x')
{
passGo = true;
}
} while (passGo == false);
Console.ReadLine();
/*
Settings s = new Settings();
s.PropertyChanged += new PropertyChangedEventHandler(S_PropertyChanged);
while (true)
{
string str = Console.ReadLine();
s.State = str;
}*/
}
public static void S_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
Settings RecSettings = (Settings)sender;
Console.WriteLine("The {0} has changed to {1}", e.PropertyName, RecSettings.State);
}
}
public class Settings : INotifyPropertyChanged
//The Class Object 'Settings' is used to recieve the variable(s) from the client software
{
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
string state = string.Empty;
public string State
{
get { return state; }
set
{
state = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("State"));
Console.WriteLine("Event has been called");
}
}
}
}
}
This is my webSocket:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using Newtonsoft.Json;
namespace HomeAutomation
{
class Socket
{
public static void WebSocketServer()
{
//Declaring variables used in the program
IPAddress ipAddress = Dns.GetHostEntry("localhost").AddressList[0];
TcpListener server = new TcpListener(ipAddress, 8080);
try
{
//Starts the server
server.Start();
Console.WriteLine("Starting Server...");
}
catch (Exception ex)
{
//If the server cannot start the error will be caught and printed to console
Console.WriteLine(ex.ToString());
Console.ReadLine();
}
while (true)
{
TcpClient client = server.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;
Settings RecSettings = new Settings();
//Lets you know the address of the connected client
string address = client.Client.AddressFamily.ToString();
Console.WriteLine("{0} has connected!", address);
//creates a network stream for information to flow through
NetworkStream stream = client.GetStream();
byte[] receivedBuffer = new byte[100];
stream.Read(receivedBuffer, 0, receivedBuffer.Length);
StringBuilder msg = new StringBuilder();
foreach (byte b in receivedBuffer)
{
if (b.Equals(00))
{
break;
}
else
{
msg.Append(Convert.ToChar(b).ToString());
}
}
Console.WriteLine("Client Says: {0}", msg.ToString());
RecSettings = JsonConvert.DeserializeObject<Settings>(msg.ToString());
Console.WriteLine(RecSettings.State.ToString());
RecSettings.State = "Off";
int byteCount = Encoding.ASCII.GetByteCount("Thank you");
byte[] sendData = new byte[byteCount];
sendData = Encoding.ASCII.GetBytes("Thank you");
stream.Write(sendData, 0, sendData.Length);
}
}
}
This is the event handler example I am using:
using System;
using System.ComponentModel;
namespace HomeAutomation
{
class Program
{
static void Main(string[] args)
{
TestClass sample = new TestClass();
sample.PropertyChanged += new PropertyChangedEventHandler(sample_PropertyChanged);
while (true)
{
string str = Console.ReadLine();
int val;
if (int.TryParse(str, out val))
sample.TestValue = val;
}
}
static void sample_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
TestClass sample = (TestClass)sender;
/*
* Use expression behind if you have more the one property instead sample.TestValue
* typeof(TestClass).GetProperty(e.PropertyName).GetValue(sample, null)*/
Console.WriteLine("Value of property {0} was changed! New value is {1}", e.PropertyName, sample.TestValue);
}
}
public class TestClass : INotifyPropertyChanged
{
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
int testValue = 0;
public int TestValue
{
get { return testValue; }
set
{
testValue = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("TestValue"));
}
}
}
}
You may want to wrap the contents of your WebSocket response in code that invokes it in the Dispatcher thread.
System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
{
... response handler code
}

Bug in TCP/IP application

I wrote a client-server app, this is a console chat application for many clients. When only one client is connected, the application works well, but when two or more clients are connected I have a bug, after sending one message to the second client, he lost connection to the server and only first client can send a message to the server...
I used Task for asynchronous operations like listening port and sending messages. When one client sends a message to the server, it adds it to the list messages and resends to all clients to refresh all windows.
Server application:
using System;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Server
{
class Program
{
private static List<Client> clients = new List<Client>();
private static TcpListener listener = null;
private static StreamReader reader = null;
private static StreamWriter writer = null;
private static List<Task> clientTasks = new List<Task>();
private static List<string> messages = new List<string>();
public static void Main()
{
Console.Title = "Server";
try
{
listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 8080);
listener.Start();
Console.WriteLine("Server started...");
var connectTask = Task.Run(() => ConnectClients());
//var listenTask = Task.Run(() => ListenClients());
Task.WaitAll(connectTask);
}
catch (Exception e)
{
Console.WriteLine(e);
}
finally
{
if (listener != null)
{
listener.Stop();
}
}
}
private static void ConnectClients()
{
Console.WriteLine("Waiting for incoming client connections...");
while (true)
{
if (listener.Pending()) //if someone want to connect
{
clients.Add(new Client(listener.AcceptTcpClient(), "Client: " + (clients.Count + 1)));
Console.WriteLine(clients[clients.Count - 1].clientName + " connected to server.");
var newClientTask = Task.Run(() => HandleClient(clients[clients.Count - 1]));
clientTasks.Add(newClientTask); //start new task for new client
}
}
}
private static void HandleClient(Client TCPClient)
{
Console.WriteLine("Starting handle client");
string s = string.Empty;
writer = new StreamWriter(TCPClient.client.GetStream());
reader = new StreamReader(TCPClient.client.GetStream());
try
{
while (!(s = reader.ReadLine()).Equals("Exit") || (s == null))
{
if(!TCPClient.client.Connected)
{
Console.WriteLine("Client disconnected.");
clients.Remove(TCPClient);
}
Console.WriteLine("From client: " + TCPClient.clientName + " -> " + s);
messages.Add(TCPClient.clientName + ": " + s); //save new message
//Console.WriteLine(s);
foreach (Client c in clients) //refresh all connected clients
{
c.writer.WriteLine("%C"); //clear client
foreach (string msg in messages)
{
c.writer.WriteLine(msg);
c.writer.Flush();
}
}
}
//CloseServer();
}
catch (Exception e) { Console.WriteLine(e); }
Console.WriteLine("ending handle client");
}
private static void CloseServer()
{
reader.Close();
writer.Close();
clients.ForEach(tcpClient => tcpClient.client.Close());
}
}
}
Client information class:
using System.Net.Sockets;
using System.IO;
namespace Server
{
class Client
{
public TcpClient client;
public StreamWriter writer;
public string clientName;
public Client(TcpClient client, string clientName)
{
this.client = client;
writer = new StreamWriter(client.GetStream());
this.clientName = clientName;
}
}
}
Client application:
using System.Net.Sockets;
using System.Net;
using System.IO;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace Client
{
class Program
{
private static TcpClient client = new TcpClient();
private static StreamReader reader;
private static StreamWriter writer;
private static bool refresh;
private static List<string> messages = new List<string>();
public static void Main()
{
Console.Title = "Client";
ConnectLoop();
//Task.WaitAll(sendTask, recieveTask); //wait for end of all tasks
}
private static void ConnectLoop()
{
bool refreshTask = false;
Task sendTask = null, recieveTask = null, updateConvTask = null;
while (true)
{
if(!client.Connected) //try to connect
{
refreshTask = true;
if(sendTask != null || recieveTask != null || updateConvTask != null)
{
sendTask.Dispose();
recieveTask.Dispose();
updateConvTask.Dispose();
sendTask = recieveTask = updateConvTask = null;
}
Console.WriteLine("Connecting to server...");
try
{
client.Connect(IPAddress.Parse("127.0.0.1"), 8080);
}
catch (SocketException) { }
Thread.Sleep(10);
}
else if(refreshTask) // \/ CONNECTED \/
{
Console.WriteLine("Connected.");
reader = new StreamReader(client.GetStream());
writer = new StreamWriter(client.GetStream());
sendTask = Task.Run(() => SendMessage()); //task for sending messages
recieveTask = Task.Run(() => RecieveMessage()); //task for recieving messages
updateConvTask = Task.Run(() => UpdateConversation()); //task for update console window
refreshTask = false;
}
}
}
private static void SendMessage()
{
string msgToSend = string.Empty;
do
{
Console.WriteLine("Enter a message to send to the server");
msgToSend = Console.ReadLine();
writer.WriteLine(msgToSend);
writer.Flush();
} while (!msgToSend.Equals("Exit"));
EndConnection();
}
private static void RecieveMessage()
{
try
{
while (client.Connected)
{
//Console.Clear();
string msg = reader.ReadLine();
if(msg != string.Empty)
{
if (msg == "%C") //special message from server, clear messages if recieve it
{
messages.Clear();
}
else
{
messages.Add(msg);
refresh = true; //refresh console window
}
}
//Console.Clear();
//Console.WriteLine(msgFromServer);
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
private static void UpdateConversation()
{
//string conversationTmp = string.Empty;
try
{
while (true)
{
if (refresh) //only if refresh
{
refresh = false;
Console.Clear();
messages.ForEach(msg => Console.WriteLine(msg)); //write all messages
Console.WriteLine();
}
}
}
catch (Exception) { }
}
private static void EndConnection()
{
reader.Close();
writer.Close();
client.Close();
}
}
}
I know that my bug will be something stupid. I'm new to TCP/IP applications, could you give me links to some tutorials that use it and Tasks?
Thanks for any help.

named pipe client won't work in unity3d

I wrote this C# code to have namedPipeServer and NamedPipeClient, with Asynchronous read and write settings, connect to each other. Both code runs perfectly on visual studio 2010 that I am using with read and write working well without any application freeze during runtime.
But I want the client side running in unity3d. The problem I encounter is in client side code implemented in Unity3D. When I use Write_to_Server_Async(string message), read in the server side is not invoked and is only invoked when I quit Unity3d (I have end its process typically). I can tell something wrong with Unity3D, because the exact code works perfectly in visual studio, so I know my code is implemented the right way. I have heard about how unity3d does not really use real threads unless user manually creates one but even that has not solved the problem. My speculation is Unity3D developers might have created their version of .NET library 3.5 (sounds bizzare (does explain why they still haven't adopted 4.5)) or somehow they must have structured their library in a way that by default functions like NamedPipeClientStream.BeginWrite cannot create its own real thread. But then again I am not sure if its the problem with threads.
At the moment, I would like anyone to come up with good explanation.
Make sure to replace Debug.WriteLine to UnityEngine.Debug.Log in unity3d.
Below is Client Main method code and class
class PipeClient
{
private static Asynchronus_NamedPipe_Client client;
static void Main(string[] args)
{
client = new Asynchronus_NamedPipe_Client("mypipe7055");
while (client.Is_connected_to_server()) {
if (Console.ReadKey().Key == ConsoleKey.T)
{
client.Write_to_Server_Async("NEX CLIENT");
}
}
}
}
Asynchronus_NamedPipe_Client class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System;
using System.IO;
using System.IO.Pipes;
using System.Text;
using System.Security.Principal;
using System.Diagnostics;
using System.Threading;
namespace NamedPipes_CLIENT
{
public class Asynchronus_NamedPipe_Client
{
public readonly string pipe_address;
private System.IO.Pipes.NamedPipeClientStream clientStream;
public bool filter_message = true;
private string Server_Message = null;
public event ASYNC_pipe_status_callback ASYNC_external_Write_Completed;
public event ASYNC_pipe_status_callback ASYNC_external_Read_Completed;
public delegate void ASYNC_pipe_status_callback(string message);
private byte[] read_buffer = new byte[1024];
private byte[] write_buffer = new byte[1024];
private IAsyncResult read_result;
private IAsyncResult write_result;
private int read_id = 1;
public Asynchronus_NamedPipe_Client(string pipe_address)
{
try
{
this.pipe_address = pipe_address;
// if(clientStream.IsConnected){UnityEngine.Debug.Log("Server Already Running");}else{}
clientStream = new NamedPipeClientStream(".", this.pipe_address, PipeDirection.InOut, PipeOptions.Asynchronous);
clientStream.Connect(1);
if (clientStream.IsConnected)
{
Console.WriteLine("Connected to Server");
Read_from_Server_Async();
}
else { Console.WriteLine("Could NOT connect to Server"); }
}
catch (Exception oEX) { Console.WriteLine("Application Pipe Error: "+oEX.Message); }
}
public void Write_to_Server_Async(string message)
{
if (clientStream != null)
{
if (clientStream.CanWrite && clientStream.IsConnected)
{
clientStream.WaitForPipeDrain();
ASCIIEncoding.ASCII.GetBytes(message).CopyTo(write_buffer,0);
clientStream.BeginWrite(write_buffer, 0, write_buffer.Length, new AsyncCallback(Async_Write_Completed), 1);
} else { close_pipe(); }
}
}
public void Read_from_Server_Async()
{
if (clientStream.CanRead && clientStream.IsConnected)
{
clientStream.BeginRead(read_buffer, 0, read_buffer.Length, new AsyncCallback(Async_Read_Completed), 2);
} else { close_pipe(); }
}
private void Async_Write_Completed(IAsyncResult result)
{
clientStream.EndWrite(result);
Debug.WriteLine("Written To Server => " + ASCIIEncoding.ASCII.GetString(write_buffer));
// close_pipe();
}
private void Async_Read_Completed(IAsyncResult result)
{
clientStream.EndRead(result);
Server_Message = ASCIIEncoding.ASCII.GetString(read_buffer);
this.Server_Message.Trim();
Console.WriteLine("Received from Server => " + Server_Message);
Debug.WriteLine("Received from Server => " + Server_Message);
if (clientStream.CanRead && clientStream.IsConnected)
{
Read_from_Server_Async();
}
else { close_pipe(); }
}
public Boolean Is_connected_to_server() {
return clientStream.IsConnected;
}
public void close_pipe()
{
if (clientStream != null)
{
if (clientStream.IsConnected)
{
clientStream.Close();
clientStream.Dispose();
Debug.WriteLine(" Pipe Closed");
}
}
}
}
}
Server side Main method implementation
static void Main(string[] args)
{
Asynchronus_NamedPipe_Server Async_server = new Asynchronus_NamedPipe_Server("mypipe7055");
while (true)
{
do
{
Async_server.Write_to_Client_Async("yeye");
Console.WriteLine("escape key");
} while (Console.ReadKey(true).Key != ConsoleKey.Escape);
}
}
Server Side Class -----
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Pipes;
using System.IO;
using System.ComponentModel;
using System.Diagnostics;
namespace Application_Pipe
{
public class Asynchronus_NamedPipe_Server
{
public readonly string pipe_address;
private System.IO.Pipes.NamedPipeServerStream namedPipeServerStream;
private string Server_Message;
public delegate void ASYNC_pipe_status_callback(string message);
private byte[] read_buffer = new byte[1024];
private byte[] write_buffer = new byte[1024];
public Asynchronus_NamedPipe_Server(string pipe_address)
{
try
{
this.pipe_address = pipe_address;
namedPipeServerStream = new NamedPipeServerStream(this.pipe_address,
PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous); //new NamedPipeServerStream(pipe_address);
Console.WriteLine("Connecting to Client...");
namedPipeServerStream.WaitForConnection();
Console.WriteLine("Connected to Client");
Read_from_Client_Async();
}
catch (Exception oEX) { Console.WriteLine(oEX.Message); }
}
public void Write_to_Client_Async(string message)
{
if (namedPipeServerStream != null)
{
if (namedPipeServerStream.CanWrite && namedPipeServerStream.IsConnected)
{
namedPipeServerStream.WaitForPipeDrain();
ASCIIEncoding.ASCII.GetBytes(message).CopyTo(write_buffer,0);
namedPipeServerStream.BeginWrite(write_buffer, 0, write_buffer.Length, new AsyncCallback(Async_Write_Completed), 2);
}
else { close_pipe(); }
}
}
public void Read_from_Client_Async()
{
if (namedPipeServerStream != null)
{
if (namedPipeServerStream.CanRead && namedPipeServerStream.IsConnected)
{
namedPipeServerStream.BeginRead(read_buffer, 0, read_buffer.Length, new AsyncCallback(Async_Read_Completed), 1);
} else { close_pipe(); }
}
}
private void Async_Read_Completed(IAsyncResult result)
{
namedPipeServerStream.EndRead(result);
this.Server_Message = ASCIIEncoding.ASCII.GetString(read_buffer);
this.Server_Message.Trim();
Debug.WriteLine("Received from Client => " + this.Server_Message+" <=REnd");
Read_from_Client_Async();
}
private void Async_Write_Completed(IAsyncResult result)
{
namedPipeServerStream.EndWrite(result);
Debug.WriteLine("Written To Client => " + ASCIIEncoding.ASCII.GetString(write_buffer));
}
public Boolean Is_connected_to_server()
{
return this.namedPipeServerStream.IsConnected;
}
public void close_pipe()
{
if(namedPipeServerStream.IsConnected){
namedPipeServerStream.Disconnect();
}
namedPipeServerStream.Close();
namedPipeServerStream.Dispose();
Debug.WriteLine(" Pipe Closed");
}
} //------class End
}

Categories

Resources