I'm facing a quite strange problem on Unity 5.2.0f3 64Bits. When I create my own custom class for a TcpClient connection, this one never gets connected. This is my simple class:
protected override void StartClient(string mod, string ip)
{
RunClient(ip, mod);
}
private ManualResetEvent connectDone = new ManualResetEvent(false);
private void connect_done(IAsyncResult ar)
{
connectDone.Set();
}
private void RunClient(string ip_host_name, string mode)
{
try
{
TcpClient client = new TcpClient();
client.BeginConnect(IPAddress.Parse(ip_host_name), 6666, new AsyncCallback(connect_done), client);
connectDone.WaitOne();
//Console.WriteLine("Connected");
SslStream lv_ssl_stream = new SslStream(client.GetStream(), false,
new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
if (authenticate_server(lv_ssl_stream, client))
{
}
else
{
// Console.WriteLine("\nCouldn't authenticate the server");
}
client.Close();
}
catch (Exception e)
{
}
}
This is a custom class which doesn't inherit from MonoBehaviour, because the idea was it to run on a different thread. When I execute the Unity app, the class instance is properly created and also executed (with/out Thread, it's for both the same behaviour).
When the process comes across client.BeginConnect() the AsyncCallback() is fired, but the client.connected is still false.
When I replace client.BeginConnect() with client.Connect() the process will hang there, and when it's not executed in a different thread, the Unity framework just dumps. (Not Responding)
I developed the class first on .Net 2012 and could execute it with all expected results (no errors).
EDIT:
When I create and ran TcpClient.Connect() in MonoBehaviour, the TcpClient gets connected to my server, but this isn't an solution for me as it's a lot of data which is getting returned.
Has somebody faced this type of problem?
Workaround for that issue was to create a normal unity C# script, placing there the whole client code.
Unity is still buggy, because the first time the code was copied, it didn't work but commenting out/in it worked (copied code of RunClient() )...
Related
I'm trying to create my own chat app as a school project.
I have almost everything ready, connected with DB, backend. The only thing that is weighing me down right now is adding a TCP Server to the project for communication between Clients.
It's not supposed to be anything big, so just short code, plus I don't have that much experience with TCP in C#.
The code works, but the problem is that the Application/Window doesn't appear.
I suspected that the problem might be in the MainWindow() constructor due to the infinite loop (this was also confirmed here on SO). Unfortunately I don't know how to fix it anymore. I first had the server as a separate class, but I ran into this problem. So I tried implementing it directly in the class, or breaking the connection after shutting down the application.
public partial class MainWindow: Window {
private TcpListener myServer;
private bool isRunning;
public MainWindow() {
InitializeComponent();
myServer = new TcpListener(IPAddress.Any, 65525);
myServer.Start();
isRunning = true;
LoopServer();
}
private void LoopServer() {
while (isRunning) {
TcpClient client = myServer.AcceptTcpClient();
Thread thread = new Thread(new ParameterizedThreadStart(LoopClient));
thread.Start(client);
}
}
private void LoopClient(object obj) {
TcpClient client = (TcpClient) obj;
StreamReader reader = new StreamReader(client.GetStream(), Encoding.UTF8);
StreamWriter writer = new StreamWriter(client.GetStream(), Encoding.UTF8);
MessageBox.Show("Connected bro!");
writer.Flush();
bool clientRunning = true;
while (clientRunning) {
string data = reader.ReadLine();
MessageBox.Show(data);
writer.Flush();
}
}
}
An infinite loop is okay for a server to be running in. Generally, you can start up the server (1st application). The clients (different application) can connect to it and then process messages and broadcast them to all the clients appropriately.
Super simple example: Build Chat in C#
Alternatively you can try an event based approach to the TCP listener.
I need a simple connectionless ClientServer application to exchange a bunch of information with a wireless device.
Before to talk about problems I'll show what I've till now:
Environment: C#, WPF, .NetFramework 4.7.1, Visual Studio 2017
Logical Organization: UDP -> UDPServer -> UDPSpecServer; UDP -> UDPClient
Code:
// Server App ctor
endPoint = new IPEndPoint(IPAddress.Any, 0);
socket.Bind(new IPEndPoint(ip, connPort));
which should basically means that I accepts packets from everyone at specified ip (localhost) / port (1984). At some point in the code I have:
public void StartReceivingConnectionless()
{
IAsyncResult result;
try
{
result = socket.BeginReceiveFrom(buffer, 0, MAX_UDP_PACKET_DIMENSION, SocketFlags.None, ref endPoint, new AsyncCallback(MessageReceived), buffer);
}
catch(Exception exception)
{
System.Diagnostics.Debug.Print(exception.Message);
}
}
which should basically means that my server object starts to wait for incoming data, while the MessageReceived method:
public virtual void MessageReceived(IAsyncResult asynchronousResult)
{
int bytes = socket.EndReceiveFrom(asynchronousResult, ref endPoint);
StartReceivingConnectionless();
}
And finally, for Serverside:
public void StopReceivingConnectionless()
{
socket.Close();
}
While on client:
// Clientapp ctor
client = new FST.Lib.NetworkCommunication.UDPClient("localhost", "0");
// On-click somewhere
client.SendConnectionless(Encoding.ASCII.GetBytes("Hello world"), new System.Net.IPEndPoint(System.Net.IPAddress.Parse("127.0.0.1"), 1984));
1) I still have to undesterstand why/how, but sometimes the app works, sometimes no: why?
2) The stopreceveing method is placed in the "Window_closing" event of main window, no matter what, it generates a disposed object exception because it generate a message which is recevied. Where should I put it?
For part 1) - it seems that my Virtual Machines was the problem. I replicated the same library at home and everything went fine. In this case, I solved using UdpClient with less or more the same architecture.
Part 2) is still a partial puzzle: I was missing the call to socket.Shutdown(); and then socket.Close(); as pointed out here but this call generates a message received from the same socket causing the crash.
I'm accepting this answer, but more detailed ones are still welcome.
I'm trying to connect through the application I'm making as a client to my phone for testing purposes, but I'm missing something. After pairing the devices, the program should open a new thread on which it runs client.BeginConnect, but it only gets as far as "Starting connect thread...".
BluetoothDeviceInfo deviceInfo;
private void listBox1_DoubleClick(object sender, EventArgs e)
{
deviceInfo = devices.ElementAt(listBox1.SelectedIndex);
updateUI(deviceInfo.DeviceName + " was selected. Attempting to connect.");
if (pairDevice())
{
updateUI("Device paired.");
updateUI("Starting connect thread...");
Thread bluetoothClientThread = new Thread(new ThreadStart(ClientConnectThread));
}
else
{
updateUI("Pairing failed.");
}
}
private void ClientConnectThread()
{
updateUI("Attempting connect.");
client.BeginConnect(deviceInfo.DeviceAddress, BluetoothService.SerialPort, new AsyncCallback(BluetoothClientConnectCallback), client);
}
I tried reusing a thread I used for scanning for devices previously and pasted the BeginConnect there, but that just makes the program crash. I'm unsure of what error it might show, because I'm programming it on my PC, but can only test the program on another laptop using the .exe file.
You have created a thread, but you haven't asked it to start yet:
Thread bluetoothClientThread = new Thread(new ThreadStart(ClientConnectThread));
bluetoothClientThread.Start(); // <--- this starts the thread
See here for details
Of course, then you have another problem because you call BeginConnect (which is asynchronous) and then the function ends (and so will the thread).
I'm trying to send and receive to/from a UDP multicast address using UWP. It works perfectly the first few times, but after a while of this send-receive process, it will lock on the receiving part. I changed from an async approach to a synchronous one but still the same. Even if I instantiate a new UDP client, the port is blocked until the app is restarted. Anything I'm doing wrong?
private UdpClient udp;
//inside main function:
if (udp == null)
{
udp = new UdpClient(new IPEndPoint(IPAddress.Any, portNumber));
//^the second time this is called, it will complain about port reuse
udp.Client.ReceiveTimeout = udp.Client.SendTimeout = 3000;
//udp.Client.SetSocketOption(SocketOptionLevel.Udp, SocketOptionName.ReuseAddress, true);
//^invalid
}
//await udp.SendAsync(data, data.Length, , portNumber);
//I changed from async to synchronous in case it was the issue, but no.
udp.Client.SendTo(data, new IPEndPoint(IPAddress.Parse(ipString), portNumber));
//the receive used to be async, too
byte[] receivedByte = new byte[udp.Client.ReceiveBufferSize];
try
{
udp.Client.Receive(receivedByte);
}
catch (Exception ex)
{
udp.Client.Shutdown(SocketShutdown.Both);
udp = null; // added these, but port still blocked until restart
}
I'm using UWP, and there are methods on class library that aren't here.
After putting UdpClient in a using () statement instead of declaring it as a private field, and limiting its scope by putting it in a short async method, I am not having these problems anymore.
A client need to build several tcp connections to server simultaneously.
My Server's code is below.
while (_running)
{
if (!_listener.Pending())
{
Thread.Sleep(100);
continue;
}
TcpClient client = _listener.AcceptTcpClient();
}
And my client's code is below.
for (int i = 0; i < num; i++)
{
TcpClient tcp = new TcpClient();
tcp.Connect(_server);
}
The first connection is success. But the second connection is failed due to server's no response(Actually server are listening tcp connection).
However, if I add Thread.Sleep(1500) after each of tcp.Connect(), all connections are success. But this situation is only true if there are one client and one server. If there are many clients then how can I ensure each connection that can be accepted by server? Also why I add Thread.Sleep can make such connections succeed?
I had the same task. I looked for canonical implementation of this task for .Net with no luck.
The approach I use now is descibed below.
Main idea
We need listener to receive connection, give the connection to the handler, and as soon as possible start listen for a new connection.
Implementation
AutoResetEvent _stopEvent = new AutoResetEvent(false);
object _lock = new object();
public void StartListening()
{
_listener.BeginAcceptTcpClient(ConnectionHandler, null);
_stopEvent.WaitOne();//this part is different in my original code, I don't wait here
}
public void StopListening()
{
lock(_lock)
{
listener.Stop();
listener = null;
}
_stopEvent.Set();//this part is different in my original code
}
void ConnectionHandler(IAsyncResult asyncResult)
{
lock(_lock)
{
if(_listener == null)
return;
var tcpClient = _listener.EndAcceptTcpClient(asyncResult);
var task = new MyCustomTask(tcpClient);
ThreadPool.QueueUserWorkItem(task.Execute);
_listener.BeginAcceptTcpClient(ConnectionHandler,null);
}
}
I am still not very confident in calling _listener.BeginAcceptTcpClient in ConnectionHandler, but I haven't found alternative way.
Since there are still no satisfied answers and I finally use different approach to handle my case. I found out that using class Socket is faster and more stable than using TcpListener and TcpClient. I tried different approach to use TcpListener and TcpClient. Firstly, I used TcpListener.AcceptTcpClient to listen client with and without TcpListener.Pending but there is still possibly ignoring some client connection. Sencondly, I used asynchronous method, TcpListener.BeginAcceptTcpClient and TcpListener.EndAcceptTcpClient but still no succeeded, still ignoring some client connection. Finally using Socket.Accept instead of TcpListener.AcceptTcpClient, the former one has nearly no delay and really fast to response to client.