using UnityEngine; | |
using UnityEngine.Networking; | |
using System; | |
using System.IO; | |
using System.Net; | |
using System.Threading; | |
public class UnityHttpListener : MonoBehaviour | |
{ | |
private HttpListener listener; | |
private Thread listenerThread; | |
void Start () | |
{ | |
listener = new HttpListener (); | |
listener.Prefixes.Add ("http://localhost:4444/"); | |
listener.Prefixes.Add ("http://127.0.0.1:4444/"); | |
listener.AuthenticationSchemes = AuthenticationSchemes.Anonymous; | |
listener.Start (); | |
listenerThread = new Thread (startListener); | |
listenerThread.Start (); | |
Debug.Log ("Server Started"); | |
} | |
void Update () | |
{ | |
} | |
private void startListener () | |
{ | |
while (true) { | |
var result = listener.BeginGetContext (ListenerCallback, listener); | |
result.AsyncWaitHandle.WaitOne (); | |
} | |
} | |
private void ListenerCallback (IAsyncResult result) | |
{ | |
var context = listener.EndGetContext (result); | |
Debug.Log ("Method: " + context.Request.HttpMethod); | |
Debug.Log ("LocalUrl: " + context.Request.Url.LocalPath); | |
if (context.Request.QueryString.AllKeys.Length > 0) | |
foreach (var key in context.Request.QueryString.AllKeys) { | |
Debug.Log ("Key: " + key + ", Value: " + context.Request.QueryString.GetValues (key) [0]); | |
} | |
if (context.Request.HttpMethod == "POST") { | |
Thread.Sleep (1000); | |
var data_text = new StreamReader (context.Request.InputStream, | |
context.Request.ContentEncoding).ReadToEnd (); | |
Debug.Log (data_text); | |
} | |
context.Response.Close (); | |
} | |
} |
It appears to work when running in editor but not on published builds, any thoughts?
It appears to work when running in editor but not on published builds, any thoughts?
I had the same issue. In my case it was because I'm not kill the tread in Unity Editor. When I stopped the play mode it continue to listen 4444 port. Then I started my build and it had a conflict for the listening the same port. You need to close Editor before start the build or add some code to kill the thread before exit the play mode in Editor .
Anyway, check the 127.0.0.1:4444 port (or your port number) in Windows console before starting the build :
$ netstat -aot
To get arround that problem I randomize the port on Awake. you can send an event with the new port used so that whatever script who needs it can grab the event.
I found this solution for me now - just added to Start method:
EditorApplication.playModeStateChanged += delegate(PlayModeStateChange state)
{
if (state == PlayModeStateChange.ExitingPlayMode)
{
listener.Stop();
listenerThread.Abort();
Debug.Log("Server stoped");
}
};
But recommend to add checking of listening to StartListener method, cause it throws an error at finish playmode:
while (true)
{
if (listener.IsListening)
{
var result = listener.BeginGetContext(ListenerCallback, listener);
result.AsyncWaitHandle.WaitOne();
}
}
Would it not be better or possible to do this with a coroutine instead of an entirely separate System.Thread?
using UnityEngine;
using UnityEngine.Networking;
using System;
using System.IO;
using System.Net;
using System.Threading.Tasks;
public class UnityHttpListener : MonoBehaviour
{
private HttpListener listener;
void Start()
{
listener = new HttpListener();
listener.Prefixes.Add("http://localhost:4444/");
listener.Prefixes.Add("http://127.0.0.1:4444/");
listener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
listener.Start();
StartCoroutine("startListenerCoroutine");
Debug.Log("Server Started");
}
private System.Collections.IEnumerator startListenerCoroutine()
{
while(listener.IsListening)
{
Task<HttpListenerContext> task = listener.GetContextAsync();
yield return new WaitUntil(() => task.IsCompleted);
ProcessRequest(task.Result);
}
}
private void ProcessRequest(HttpListenerContext context)
{
Debug.Log("Method: " + context.Request.HttpMethod);
Debug.Log("LocalUrl: " + context.Request.Url.LocalPath);
if (context.Request.QueryString.AllKeys.Length > 0) {
foreach (var key in context.Request.QueryString.AllKeys) {
Debug.Log ("Key: " + key + ", Value: " + context.Request.QueryString.GetValues(key)[0]);
}
}
if (context.Request.HttpMethod == "POST") {
var data_text = new StreamReader (context.Request.InputStream, context.Request.ContentEncoding).ReadToEnd();
Debug.Log (data_text);
}
context.Response.StatusCode = 200;
context.Response.StatusCode = "OK";
context.Response.Close ();
}
void OnApplicationQuit() {
listener.Stop();
Debug.Log("Server stoped");
}
}
https://gist.github.com/PikaChokeMe/7604fa19596ea6f66019898a948a8dd2
I will say that I don't know the performance implications of this over the dedicated thread; however.
Does anyone know why he put
Thread.Sleep (1000);
on line 52? Why do you need aThread.Sleep()
there?