为什么会有这个需求呢,是这样的,我们希望在手机端能够实时的把日志汇报到一个测试用的服务器上。因为本人是客户端,而且也不想占用服务器资源。因此就想自己尝试一下能不能直接用C#实现一个简单的http服务器,搜了一些资料后发现。一种是用Socket实现,一种是用HttpListener实现。Socket的实现不够直观明朗,但是更灵活。因为我的需求就是期望客户端那用简单的http请求就可以把游戏内日志汇报上来,因此简单易用是第一需求。
原作者找不到了,这是我找到的那个参考
https://www.h3399.cn/201709/136120.html
在他的基础上,我经过修改测试,整理了一个可用的代码如下:
我是VS2019的一个WinForm工程
class SimpleHttpServer
{
private HttpListener _listener;
public SendOrPostCallback Handler = null;
public SynchronizationContext UiContext = null;
private void RequestHandler(IAsyncResult result)
{
try
{
HttpListenerContext context = _listener.EndGetContext(result);
byte[] buffer = new byte[8096];
using (Stream stream = context.Request.InputStream)
{
int count = 0;
while ((count = stream.Read(buffer, 0, buffer.Length)) > 0)
{
UiContext.Send(Handler, Encoding.UTF8.GetString(buffer, 0, count));
}
}
StreamWriter sw = new StreamWriter(context.Response.OutputStream, Encoding.UTF8);
context.Response.ContentType = "text/html";
context.Response.ContentEncoding = Encoding.UTF8;
context.Response.Close();
}
catch (Exception e)
{
//
}
finally
{
if (_listener.IsListening)
{
_listener.BeginGetContext(RequestHandler, new object());
}
}
}
public void Start()
{
_listener = new HttpListener();
_listener.Prefixes.Add("http://+:10086/");
_listener.Start();
_listener.BeginGetContext(RequestHandler, new object());
}
public void Close()
{
_listener.Stop();
_listener.Abort();
}
}
请注意,这里我什么也没有返回,因为我需要的就是仅接受到消息就OK
启用的时候,在界面初始化的时候,调用Start()方法即可,然后测试可以在浏览器上输入局域网的IP地址测试
例如http://192.168.xx.xx:10086
这里10086也是自己随便定义的一个端口,如果显示一个空白的页面,证明消息就收到了。
try内是服务器收到请求的处理,因为我是用Winform做的,涉及到一个UI线程同步问题,因此用了SynchronizationContext 来处理。实际上可以根据自己的需求去处理这个string字段
在Unity里,可以用UnityWebRequest来简单模拟,这样调用
using (UnityWebRequest unityWebRequest = new UnityWebRequest(_uri, UnityWebRequest.kHttpVerbPOST))
{
unityWebRequest.uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(log))
{
contentType = "application/x-www-form-urlencoded"
};
unityWebRequest.timeout = 3;
unityWebRequest.useHttpContinue = false;
yield return unityWebRequest.SendWebRequest();
}
log就是我们要发送的日志内容本身。
需要注意的一点是,运行服务器的主机一定要关掉防火墙,或者加入白名单,不然会有可能造成别的机器无法访问的问题。另外我只测试了内网。外网的情况下,可能需要IP映射
附:
在安卓上测试也是OK的,还没在Ios上测试,后续测试过了也补充进来
另外,unity可以通过
Application.logMessageReceivedThreaded += OnLogHandle
方法来监听所有日志,在应用里,只需要添加自己处理日志的方法即可。为了不阻塞游戏,请做个缓存队列~不然经常卡死unity。试想,如果你在错误日志处理里也出错,这个错误又会触发错误日志处理,就直接死循环了。反正要注意下这个问题