Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by Paulo-Henrique025 · Sep 18, 2012 at 04:05 PM · networkserversocketstcp

How to do a TCP Server?

Hi guys, I think my last question was misinterpreted, so here is a more simple one.

How to create a TCP server and Client in unity? I don't want to use unity network layer, this game will connect to a C++ server so I need it to talk to this server someway.

I'm completely lost, all my tries resulted in failure.

Edit:

This the code that is problematic, whenever i call "Socket soc = listener.AcceptSocket();"Unity crashes, I've tried putting it inside a coroutine without sucess.

 using System;
 using System.Collections;
 using System.IO;
 using System.Net;
 using System.Net.Sockets;
 
 public class ServerClass : MonoBehaviour
 {
     TcpListener listener;
     
     public void Start()
     {
         listener = new TcpListener(2033);
         listener.Start();
     }
     
     public void Update()
     {
             if(!listener.Pending())
         {
             Debug.Log("Nothing to do here");
         }
         else
         {
         
         Socket soc = listener.AcceptSocket();
 
                 [...]
             }
        }
 }
Comment
Add comment · Show 5
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image whydoidoit · Sep 18, 2012 at 04:09 PM 0
Share

I'm no expert - but have you looked through this

avatar image Paulo-Henrique025 · Sep 18, 2012 at 04:10 PM 0
Share

I already did it, every implementation I did in unity resulted in failure.

avatar image whydoidoit · Sep 18, 2012 at 04:11 PM 0
Share

Yeah figured you might have done. Ah well...

avatar image MadDave · Sep 18, 2012 at 04:16 PM 0
Share

"Failure" is not a problem description I can work with. If you have really tried anything (have you?) you should be able to post some code and ask a more concrete question.

avatar image Paulo-Henrique025 · Sep 18, 2012 at 04:24 PM 0
Share

Edited with proper code

4 Replies

· Add your reply
  • Sort: 
avatar image
2
Best Answer

Answer by whydoidoit · Sep 18, 2012 at 05:35 PM

Ok so you can use my Loom class to interact with other thread (per the comments to my answer above - this is too long to be a comment) which lets you do this:

  void Update()  {
      if(somethingHappened) 
      {
        Loom.RunAsync(()=>{
             //Your other thread code goes here
             //e.g. SendStuff();
 
 
 
             //If you need to then call back to the game
             Loom.QueueOnMainThread(()=>{
                   //Code triggered from the other thread that
                   //accesses Unity object goes here
                });
        });
     }
 }
 

Loom.cs

 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
 using System;
 using System.Threading;
 using System.Linq;
             
 //Loom handles threading
 public class Loom : MonoBehaviour
 {
     private static Loom _current;
         
     public static Loom Current
     {
         get
         {
             if (_current == null && Application.isPlaying)
             {
                 
                 var g = GameObject.Find("Loom");
                 if(g==null)
                 {
                     g = new GameObject("Loom");
                     g.hideFlags = HideFlags.HideAndDontSave;
                 }
                 
                 _current = g.GetComponent<Loom>() ?? g.AddComponent<Loom>();
             }
                         
             return _current;
         }
     }
     
     void Awake()
     {
         if(_current != null && _current != this)
         {
             DestroyImmediate(gameObject);
         }
         else
         {
             _current = this;
         }
     }
         
     private List<Action> _actions = new List<Action>();
     public class DelayedQueueItem
     {
         public float time;
         public Action action;
         public string name;
     }
     private List<DelayedQueueItem> _delayed = new  List<DelayedQueueItem>();
                 
     public static void QueueOnMainThread(Action action, float time, string name)
     {
         lock(Current._delayed)
         {
             if(Current._delayed.Any(d=>d.name==name))
                 return;
             QueueOnMainThread(action, time);
         }
     }
     
     public static void QueueOnMainThread(Action action, string name)
     {
         QueueOnMainThread(action, 0, name);
     }
     
     public static void QueueOnMainThread(Action action, float time)
     {
         if (time != 0)
         {
             lock (Current._delayed)
             {
                 Current._delayed.Add(new DelayedQueueItem { time = Time.time + time, action = action});
             }
         }
         else
         {
             lock (Current._actions)
             {
                 Current._actions.Add(action);
             }
         }
     }
     
     public static void QueueOnMainThread(Action action)
     {
         lock (Current._actions)
         {
             Current._actions.Add(action);
         }
     }
                 
     public static void RunAsync(Action a)
     {
         var t = new Thread(RunAction);
         t.Priority = System.Threading.ThreadPriority.Normal;
         t.Start(a);
     }
                 
     private static void RunAction(object action)
     {
         ((Action)action)();
     }
     
                 
     Action[] toBeRun = new Action[1000];
     DelayedQueueItem[] toBeDelayed = new DelayedQueueItem[1000];
     
     void Update()
     {
         try
         {
             var actions = 0;
             var delayedCount = 0;
             //Process the non-delayed actions
             lock (_actions)
             {
                 for(var i = 0; i < _actions.Count; i++)
                 {
                     toBeRun[actions++] = _actions[i];
                     if(actions==999)
                         break;
                 }
                 _actions.Clear();
             }
             for(var i = 0; i < actions; i++)
             {
                 var a = toBeRun[i];
                 try            
                 {
                     a();
                 }
                 catch (Exception e)
                 {
                     Debug.LogError("Queued Exception: " + e.ToString());
                 }
             }
             lock (_delayed)
             {
                 for(var i = 0; i <_delayed.Count; i++)
                 {
                     var d = _delayed[i];
                     if(d.time < Time.time)
                     {
                         toBeDelayed[delayedCount++]= d;
                         if(delayedCount==999)
                             break;
                     }
                 } 
             }
             for(var i = 0; i < delayedCount; i++)
             {
                 var delayed = toBeDelayed[i];
                 lock (_delayed)
                 {
                     _delayed.Remove(delayed);
                 }
                 try
                 {
                     delayed.action();
                 }
                 catch (Exception e)
                 {
                     Debug.LogError("Delayed Exception:" + e.ToString());
                 }
             }
             
         }
         catch(Exception e)
         {
             Debug.LogError("Loom Error " + e.ToString());
         }
     }
 }
         
Comment
Add comment · Show 14 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Paulo-Henrique025 · Sep 18, 2012 at 06:26 PM 0
Share

Nice!!! But i didn't get somethings. How to call this lambda code? Can i put it inside a function like this?

 void AsyncSendStuff()
 {
 
   Loom.RunAsync(()=>{
 
            [...]
 
            //If you need to then call back to the game
            Loom.QueueOn$$anonymous$$ainThread(()=>{ [...]});
            });
 }

And about this function "Loom.QueueOn$$anonymous$$ainThread(()=>{});"I didn't get it, can you please post and example?

Thanks for everything, you have done so much to help!

avatar image whydoidoit · Sep 18, 2012 at 06:30 PM 0
Share

So you can put any code you like where you have [...] in your example - it can access local variables, class variables etc etc and call anything BUT nothing must touch a Unity object (read or update it in any way) or it will fail. So you can call your code to send to the server etc. Let's imagine that the server returns am X,Y,Z coordinate that you are supposed to update the game object with - you can't do that in a second thread - hence the QueueOn$$anonymous$$ainThread.

   Loom.RunAsync(()=>{
            var newPosition = SomehowGetVector3FromServer();
            Loom.QueueOn$$anonymous$$ainThread(()=>{
                    transform.position = newPosition;
            });
   });
avatar image Paulo-Henrique025 · Sep 18, 2012 at 06:34 PM 0
Share

I thought it would be something like that, sorry, never used lambda before.

I'll implement right now.

avatar image whydoidoit · Sep 18, 2012 at 06:37 PM 0
Share

Very powerful - especially the local variable access stuff. Closures are cool :)

No threading is easy and it is damn easy to call something, that calls something that accesses a Unity object and bang. But your case is ideal for this approach - write all the blocking code you like in the lambda and it will run alongside the game - just use the QueueOn$$anonymous$$ainThread to actually change something in your game due to the server.

avatar image whydoidoit · Sep 18, 2012 at 06:39 PM 0
Share

The code in QueueOn$$anonymous$$ainThread will run during the current or next frame depending on where it is during your async queue call. You can also pass a parameter to delay it for a period of time - but I doubt that you will need that.

Show more comments
avatar image
2

Answer by whydoidoit · Sep 18, 2012 at 04:28 PM

AcceptSocket is a blocking call - you don't want to be calling that unless you know that there is a request pending - you can tell that using this. Otherwise Unity will hang until a request appears.

Coroutines are not threads - a coroutine that blocks will lock up Unity.

Comment
Add comment · Show 5 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Paulo-Henrique025 · Sep 18, 2012 at 04:39 PM 0
Share

I will try this right now!

avatar image Paulo-Henrique025 · Sep 18, 2012 at 04:50 PM 0
Share

It's not crashing anymore! At least in idle state, but when I try to send a message using the following code unity crashes just like before. Also I will update the code in my question with your hint.

 void Sendstuff()
     {
         TcpClient client = new TcpClient("127.0.0.1", 2055);
         try
         {
             Stream s = client.GetStream();
             StreamReader sr = new StreamReader(s);
             StreamWriter sw = new StreamWriter(s);
             sw.AutoFlush = true; 
             string name = "$$anonymous$$SG";
             sw.WriteLine(name);
             s.Close();
         }
         finally
         {
             client.Close();
         }
     }

avatar image whydoidoit · Sep 18, 2012 at 04:57 PM 0
Share

That code blocks too... You need to by using Asynchronous IO or have this stuff happening on another thread. Take a look at the Async methods here - it might be enough just to call FlushAsync() but I don't know what that would do with your close. I really think you should consider spinning up a thread for this.

avatar image Paulo-Henrique025 · Sep 18, 2012 at 05:09 PM 0
Share

There is no FlushAsync() method on my StreamWriter but thats no problem. I'll create a thread, but I don't know how exactly, can I follow this example link? But I will only use the Start call and let the thread finishes by itself, right?

avatar image whydoidoit · Sep 18, 2012 at 05:36 PM 0
Share

See answer below - too long for a comment.

avatar image
1

Answer by salat · Jul 30, 2013 at 08:29 PM

Check this brilliant presentation. There is a chapter with full example based on .net sockets, server and client side. Very clean and easy code. You will realize why async socket operations like BeginConnect, BeginReceive and so are needed to make it running with Unity.

http://video.unity3d.com/video/6947115/unite-2012-unity-network

UPDATE: somehow original ^^^ video not available anymore, so mirror:

http://youtu.be/SeOuGG_y8MQ

https://github.com/AngryAnt/Unity--Network-Code-and-You

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Paulo-Henrique025 · Aug 01, 2013 at 05:41 AM 1
Share

Thank you for the interest in the topic, I've bookmarked your links :)

avatar image PJvG1990 · Apr 09, 2014 at 02:53 PM 1
Share

The video is not available anymore..

avatar image salat · Apr 10, 2014 at 07:43 AM 0
Share

http://youtu.be/SeOuGG_y8$$anonymous$$Q same video

avatar image PJvG1990 · Apr 11, 2014 at 05:12 PM 0
Share

Thanks! :)

avatar image
0

Answer by MadDave · Sep 18, 2012 at 04:14 PM

If you are going to connect to a C++ Server, why do you want to create a TCP server in Unity? And since you don't want to use the Unity network layer, this is not a Unity question any more.

Anyway, the answer is "Use a socket API you like." Let me google this for you... like this one: http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.aspx

Hope it helps.

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Paulo-Henrique025 · Sep 18, 2012 at 04:19 PM 0
Share

.Net Sockets support is a Unity3D feature exposed in the licenses page. I'm having problems implementing it. Also, by server I meant just a TCPListener, so i can catch messages.

avatar image salat · Aug 01, 2013 at 06:39 AM 0
Share

1) one might not want to use Unity Network. many reasons. 2) using .net sockets in Unity application have some specifics. For example right now I am trying to figure out how to prevent .net socket asyncronious callbacks sometime being called from Unity working thread. Avoid blocking of Unity thread is a main concern.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

13 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Error: The requested address is not valid in its context. 1 Answer

TcpListener with Network Manager 1 Answer

Network Connections in Editor 1 Answer

Is there any difference calling Network.Disconnect or Network.CloseConnection from client? 1 Answer

May I control the game of a client through pressing some GuiButtons in the server application? 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges