I run client code on Unity and server code on a console application. The problem is that when the server sent a 'welcome' message to the client, the client receives an empty message. But weirdly when I run the code on Unity in debug mode it works well. Does anyone know why this happens?
Here is the client code
public class Test: MonoBehaviour
{
TcpClient client;
NetworkStream networkStream;
string stringData;
byte[] data;
private void Start()
{
StartClient();
}
private void OnApplicationQuit()
{
if (networkStream != null)
{
if (networkStream.CanRead && networkStream.CanWrite) networkStream.Close();
}
if (client.Connected) client.Close();
}
private void StartClient()
{
client = new TcpClient();
client.BeginConnect("127.0.0.1", 7777, DefaultConnectCallback, client);
}
private void DefaultConnectCallback(IAsyncResult ar)
{
TcpClient client = (TcpClient)ar.AsyncState;
networkStream = client.GetStream();
data = new byte[1024];
networkStream.BeginRead(data, 0, data.Length, DefaultReadCallback, networkStream);
stringData = System.Text.Encoding.ASCII.GetString(data).Trim('\0');
Log.LogMessage("Recieved a message");
Log.LogMessage(stringData);
Log.LogMessage($"{stringData.Length}");
}
private void DefaultReadCallback(IAsyncResult ar)
{
NetworkStream networkStream = (NetworkStream)ar.AsyncState;
networkStream.EndRead(ar);
}
}
Here is the server code
class Program
{
public static Action OnExit;
static void Main(string[] args)
{
AppDomain.CurrentDomain.ProcessExit = new EventHandler(OnProcessExit);
TcpListener listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 7);
listener.Start();
Log.LogMessage("Server Started");
OnExit = () =>
{
foreach(var client in clients)
{
client?.GetStream()?.Close();
}
listener.Stop();
};
listener.BeginAcceptTcpClient(DefaultAcceptCallback, listener);
Console.ReadKey();
}
static void OnProcessExit(object sender, EventArgs e)
{
if (OnExit != null) OnExit();
}
static TcpClient[] clients = new TcpClient[10];
static int connection = 0;
static void DefaultAcceptCallback(IAsyncResult ar)
{
TcpListener listener = (TcpListener)ar.AsyncState;
TcpClient newClient = listener.EndAcceptTcpClient(ar);
NetworkStream networkStream = newClient.GetStream();
byte[] welcome;
Log.LogMessage($"Connect request No.{connection} accepted");
clients[connection] = newClient;
welcome = Encoding.ASCII.GetBytes("Welcome!");
networkStream.BeginWrite(welcome, 0, welcome.Length, DefaultReadCallback, networkStream);
Log.LogMessage($"Welcome message sent");
connection ;
listener.BeginAcceptTcpClient(DefaultAcceptCallback, listener);
}
static void DefaultWriteCallback(IAsyncResult ar)
{
NetworkStream networkStream = (NetworkStream)ar.AsyncState;
networkStream.EndWrite(ar);
}
}
CodePudding user response:
networkStream.BeginRead(data, 0, data.Length, DefaultReadCallback, networkStream);
is a non-blocking call and you immediately continue with your code.
You have to wait until actually something has been received!
private void DefaultConnectCallback(IAsyncResult ar)
{
TcpClient client = (TcpClient)ar.AsyncState;
networkStream = client.GetStream();
data = new byte[1024];
networkStream.BeginRead(data, 0, data.Length, DefaultReadCallback, networkStream);
}
private void DefaultReadCallback(IAsyncResult ar)
{
NetworkStream networkStream = (NetworkStream)ar.AsyncState;
networkStream.EndRead(ar);
stringData = System.Text.Encoding.ASCII.GetString(data).Trim('\0');
Log.LogMessage("Recieved a message");
Log.LogMessage(stringData);
Log.LogMessage($"{stringData.Length}");
}
See NetworkStream.BeginRead
and also the example of NetworkStream.EndRead