- Home /
TCP/IP data transfer freeze the unity while transfering the data.
Hello guys, I am working on a unity project where user can send data from client to server using TCP/IP. I am able to send the data. But my unity stalls or freeze until the data got read from the networkstream.
Server Code:Read Data.
void Start () {
StartServer ();
startServerButton.interactable = true;
closeServerButton.interactable = false;
}
public void StartServer (){
// Start TcpServer background thread
tcpListenerThread = new Thread (new ThreadStart(ListenForIncommingRequests));
tcpListenerThread.IsBackground = true;
tcpListenerThread.Start();
startServerButton.interactable = false;
path = UnityEditor.EditorUtility.SaveFolderPanel ("Any type of File.", "", ""); // Path.Combine(path,"D:\\Siva\\TCPDownloadfiles");
}
// Update is called once per frame
void Update () {
if (Input.GetKeyDown(KeyCode.Space)) {
SendMessage();
}
if (myBackgroundWorker != null) myBackgroundWorker.Update();
}
/// <summary>
/// Runs in background TcpServerThread; Handles incomming TcpClient requests
/// </summary>
private void ListenForIncommingRequests () {
// Thread threadForDownloading = new Thread (new ThreadStart(DownloadingStreamData));
// threadForDownloading.IsBackground = true;
// threadForDownloading.Start();
DownloadingStreamData ();
}
private void DownloadingStreamData()
{
try {
Debug.Log("Befor Background work ........."+Thread.CurrentThread.Name);
if (myBackgroundWorker != null) myBackgroundWorker.CancelAsync();
myBackgroundWorker = new BackgroundThreading();
fileCount++;
int fileNameLen;
byte[] incommingData = new byte[1024];
string ext = "";
// Create listener on localhost port 8052.
tcpListener = new TcpListener(IPAddress.Parse("127.0.0.1"), 8052);
tcpListener.Start();
Debug.Log("Server is listening");
bytes = new Byte[Int32.MaxValue]; // 2221024
while (true) {
connectedTcpClient = tcpListener.AcceptTcpClient();
stream = connectedTcpClient.GetStream();
myBackgroundWorker.BackgroundWorkStart += (obj, attr) =>
{
if (attr.IsCanceled) return;
Debug.Log("Background work In Progress...");
do{
// IAsyncResult result = stream.BeginRead(bytes, 0, bytes.Length, MessageReceived, stream);
// result.AsyncWaitHandle.WaitOne();
Debug.Log("Befor Stream Read.........."+Thread.CurrentThread.Name+" a.result : "+attr.Result+" attr.argument : "+attr.Argument+";");
length = stream.Read(bytes, 0, bytes.Length);
Debug.Log("After Stream Read.........."+length);
incommingData = new byte[length];
Array.Copy(bytes, 0, incommingData, 0, length - 4);
// Convert byte array to string message.
fileNameLen = BitConverter.ToInt32(incommingData, 0);
string clientMessage = Encoding.ASCII.GetString(incommingData,4, fileNameLen);
ext = Path.GetExtension(clientMessage);
//Debug.Log("client message received as: " + clientMessage);
//File.WriteAllBytes(path + "\\temp"+fileCount.ToString()+ext, incommingData);
// Read incomming stream into byte arrary.
}while(stream.DataAvailable);
BinaryWriter bWrite = new BinaryWriter(File.Open(path + "\\temp"+fileCount.ToString()+ext, FileMode.Create)); ;
bWrite.Write(incommingData, 4 + fileNameLen, length - 4 - fileNameLen);
bWrite.Flush();
bWrite.Close();
//Debug.Log("Bytes length2 :>>>"+" "+fileNameLen +" Incoming data length" +incommingData.Length);
//connectedTcpClient.Close();
//stream.Flush();
//stream.Close();
};
myBackgroundWorker.BackgroundWorkCompleted += (obj, attr) =>
{
Debug.Log("Background work was completed..."+Thread.CurrentThread.Name+" attr.result : "+attr.Result+" Error :"+attr.Error);
};
myBackgroundWorker.RunWorkerAsync("Test");
}
}
catch (SocketException socketException) {
Debug.Log("SocketException " + socketException.ToString());
}
}
/// <summary>
/// Send message to client using socket connection.
/// </summary>
public void SendMessage() {
if (connectedTcpClient == null) {
return;
}
try {
// Get a stream object for writing.
NetworkStream stream = connectedTcpClient.GetStream();
if (stream.CanWrite) {
string serverMessage = "This is a message from your server.";
// Convert string message to byte array.
byte[] serverMessageAsByteArray = Encoding.ASCII.GetBytes(serverMessage);
// Write byte array to socketConnection stream.
stream.Write(serverMessageAsByteArray, 0, serverMessageAsByteArray.Length);
Debug.Log("Server sent his message - should be received by client");
}
}
catch (SocketException socketException) {
Debug.Log("Socket exception: " + socketException);
}
}
//Callback called when "BeginRead" is ended
private void MessageReceived(IAsyncResult result)
{
Debug.Log("On MessageReceived::::::::::::::::::::::::::");
//length = stream.Read(bytes, 0, bytes.Length);
if (result.IsCompleted && connectedTcpClient.Connected)
{
//build message received from client
s_bytesReceived = stream.EndRead(result); //End async reading
//s_receivedMessage = Encoding.ASCII.GetString(bytes, 0, s_bytesReceived); //De-encode message as string
Debug.Log("result.IsCompleted on MessageReceived::::::::::::::::::::::::::"+s_bytesReceived);
}
}
public void CloseServer()
{
Debug.Log("Server Closed");
//Close client connection
if (connectedTcpClient != null)
{
stream.Close ();
stream = null;
connectedTcpClient.Close();
connectedTcpClient = null;
}
//Close server connection
if(tcpListener != null)
{
tcpListener.Stop();
tcpListener = null;
startServerButton.interactable = true;
closeServerButton.interactable = false;
}
}
}
I tried using stream.BeginRead method but that is throwing exception like Stream/socket was disposed already and trying to access it on client code.
But stream.Read method works as like i expect but it stalls/freeze the unity until it get the data.Please give me some better solution for this issue. Thanks in advance.
Client Code: Sends Data if (stream.CanWrite) { string path = UnityEditor.EditorUtility.OpenFilePanel ("Any type of File.", "", ""); WWW www = new WWW ("file:///" + path);
byte[] fileNameBytes = Encoding.ASCII.GetBytes(path);
byte[] fileDataBytes = www.bytes;
byte[] fileNameLength = BitConverter.GetBytes(fileNameBytes.Length);
clientData = new byte[4 + fileNameBytes.Length + fileDataBytes.Length];
fileNameLength.CopyTo(clientData, 0);
fileNameBytes.CopyTo(clientData, 4);
fileDataBytes.CopyTo(clientData, 4 + fileNameBytes.Length);
Debug.Log ("FIle sends to server path : "+path);
//stream.BeginRead(clientData, 0, clientData.Length, MessageReceived, stream);
try {
stream.Write(clientData, 0, clientData.Length);
//stream.BeginWrite(clientData, 0, clientData.Length, MessageReceived, stream);
}catch (Exception e) {
Debug.Log("SocketException " + e.ToString());
}
The server code which i have given above is altogether on the seperate thread. but still is stalls that separate thread itself.
Of course this code will block the thread it runs on. That's the point why using a seperate thread. However blocking a background worker thread will not block Unity's main thread. If yout Unity freezes then you most likely do not run your code in a seperate thread. Are you sure you run that code in a seperate thread? $$anonymous$$eep in $$anonymous$$d that Coroutines are not threads at all. They run completely on the main thread (in cooperative, hence co-routines). If a coroutine blocks it will block the whole main thread.
You didn't show enough context to judge where you might went wrong. Also you didn't format your code properly which makes it very hard to read your code. Just select the whole code section and press the 101/010 button.
Hi Bunny83, I have updated my server script. Please have a look on it. I am using multithreading even though it blocks the main thread. I dont understand how it blocks main thread.
Sorry, but at this line:
tcpListenerThread.Start();
The newly created thread is completely independent from the main thread. Blocking this thread has no influence on the main thread.
The only thing that could possibly block your main thread from what you have posted is your Send$$anonymous$$essage method when you press space or your mysterious myBackgroundWorker.Update();
call. Since we don't know what your "BackgroundThreading" class and its Update method does I would guess the issue is in there. You seem to create a delegate / lambda expression inside your background thread which you register to a delegate in your BackgroundThreading class. If you call that "BackgroundWorkStart" delegate from inside Update, you actually execute all this code on the main thread ins$$anonymous$$d of executing it in the background thread.
So without knowing what you do inside your "BackgroundThreading" class we can't say where you went wrong. However there are already several really strange and dangerous conceptional issues already. First of all you seem to allocate a 2 giga byte array (which is insane to begin with) which seems to be shared between all your connected clients. You don't really have any concept how you manage connected clients. For each client you just add another anonymous delegate. Those can't be removed in a controlled way since there's no relation between a certain client connection and the delegates.
So this question is still lacking the important information to understand what is happening. I highly recommend you look up some basic multi threading material, especially about data sharing between threads and synchonisation.
Hi Bunny, Forget about background worker. i added and tried at the later stage. If i ignored all background worker class and all its functionality still it is blockimg the main thread. i created new thread on another thread. still it halts the unity.
Answer by thelghome · Jul 11, 2019 at 03:33 PM
It's frozen because you are using thread blocking method for receiving data. You may use async read method without blocking your main thread. but current version of unity, async write didn't work well if you have async read running. I suggested you to use multi-threading solution. I recommended that you may try this plugin, there are many good example scenes related to UDP + TCP, simple message, streaming, network discovery...etc
FM Exhibition Tool Pack | Forum
Provides demos of in-game view/live video, audio streaming solution. All codes are written in C# and you can freely customise for your own project.
Supported Platforms: iOS/Android/Mac/PC
Your answer
Follow this Question
Related Questions
use TCP instead UDP 0 Answers
GPS Raspberry WiFi to Unity3d data communication 1 Answer
TcpClient not working when building, 1 Answer
TcpListener with Network Manager 1 Answer