Giter VIP home page Giter VIP logo

rrqm / touchsocket Goto Github PK

View Code? Open in Web Editor NEW
798.0 18.0 124.0 365.43 MB

TouchSocket是.Net(包括 C# 、VB.Net、F#)的一个整合性的、超轻量级的网络通信框架。包含了 tcp、udp、ssl、http、websocket、rpc、jsonrpc、webapi、xmlrpc等一系列的通信模块。一键式解决 TCP 黏分包问题,udp大数据包分片组合问题等。使用协议模板,可快速实现「固定包头」、「固定长度」、「区间字符」等一系列的数据报文解析。

Home Page: https://touchsocket.net/

License: Apache License 2.0

C# 74.30% MDX 25.08% PowerShell 0.08% TypeScript 0.55%
iocp memory-pool tcp rpc udp webapi xmlrpc-server jsonrpc-server websocket csharp ssl-support socket socket-io http https modbus

touchsocket's Issues

WebSocketPluginBase 中用HttpSocketClient的close方法无法关闭连接

你好请教一下,当我使用websocker,在protected override void OnHandleWSDataFrame(HttpSocketClient client, WSDataFrameEventArgs e)中使用client.close("message");这样关闭连接,但是从客户端看来,这个连接没有被关闭。我想完成的功能是在某些情况下,websocker服务端可以主动关闭连接。请指教该如何使用。谢谢

UDP包回复异常

连续向多点发送udp包,收不到回复。
且再向单点发包也收不到回复。
image

创建Aot项目Websocket启动报错 “Dynamic code generation is not supported on this platform”

版本:2.0.0-beta.268

[AddSingletonInject(typeof(IPluginManager), typeof(PluginManager))]
[AddSingletonInject(typeof(ILog),typeof(LoggerGroup))]
[AddSingletonInject(typeof(WebSocketFeature))]
[GeneratorContainer]
public partial class CanAotContainer : ManualContainer
{

}

static void Main(string[] args)
{

    var service = new HttpService();
    service.Setup(new TouchSocketConfig()//加载配置
        .SetListenIPHosts(7789)
        .SetRegistrator(new CanAotContainer())
        .ConfigureContainer(a =>//容器的配置顺序应该在最前面
        {
            a.AddConsoleLogger();//添加一个控制台日志注入(注意:在maui中控制台日志不可用)
            a.RegisterSingleton(service);//将服务器以单例注入。便于插件或其他地方获取。
        })
        .ConfigurePlugins(a =>
        {
            a.UseWebSocket()//添加WebSocket功能
                .SetWSUrl("/ws")//设置url直接可以连接。
                .SetVerifyConnection(VerifyConnection)
                .UseAutoPong();//当收到ping报文时自动回应pong

            a.Add<CloseExceptionPlugin>();
            a.Add<MessageRelayPlugin>();
            a.Add<DisconnectedPlugin>();
        }));

    service.Start();
    service.Logger.Info("服务器已启动");

    Console.ReadKey();
}

Unhandled exception. System.PlatformNotSupportedException: Dynamic code generation is not supported on this platform.
at System.Reflection.Emit.AssemblyBuilder.ThrowDynamicCodeNotSupported()
at System.Reflection.Emit.AssemblyBuilder.EnsureDynamicCodeSupported()
at System.Reflection.Emit.DynamicMethod.Init(String name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] signature, Type owner, Module m, Boolean skipVisibility, Boolean transparentMethod)
at System.Reflection.Emit.DynamicMethod..ctor(String name, Type returnType, Type[] parameterTypes, Module m)
at TouchSocket.Core.Method.CreateILInvoker(MethodInfo methodInfo) in D:\CodeOpen\TouchSocketPro\Src\TouchSocket.Core\Reflection\Method.cs:line 363
at TouchSocket.Core.Method..ctor(MethodInfo method, Boolean build) in D:\CodeOpen\TouchSocketPro\Src\TouchSocket.Core\Reflection\Method.cs:line 83
at TouchSocket.Core.Method..ctor(MethodInfo method) in D:\CodeOpen\TouchSocketPro\Src\TouchSocket.Core\Reflection\Method.cs:line 59
at TouchSocket.Core.PluginManager.TouchSocket.Core.IPluginManager.Add(IPlugin plugin) in D:\CodeOpen\TouchSocketPro\Src\TouchSocket.Core\Plugins\PluginManager.cs:line 90
at TouchSocket.Core.PluginManager.TouchSocket.Core.IPluginManager.Add(Type pluginType) in D:\CodeOpen\TouchSocketPro\Src\TouchSocket.Core\Plugins\PluginManager.cs:line 126
at TouchSocket.Core.PluginManagerExtension.Add[TPlugin](IPluginManager pluginManager) in D:\CodeOpen\TouchSocketPro\Src\TouchSocket.Core\Plugins\PluginManagerExtension.cs:line 31
at TouchSocket.Core.WebSocketPluginManagerExtension.UseWebSocket(IPluginManager pluginManager) in D:\CodeOpen\TouchSocketPro\Src\TouchSocket.Http\WebSockets\Extensions\WebSocketPluginsManagerExtension.cs:line 28

远程终端拒绝该操作

RemoteDirectoryInfoResult rootDirectoryInfoResult =await client.GetDirectoryInfoAsync(@"E:\backup\");
E:\backup为远程服务器(公网IP)上的文件夹,
结果:
fileinfo:null
Message:远程终端拒绝该操作,反馈信息:。
ResultCode:TouchSocket.Core.ResultCode.Error

NATService 的逻辑问题

目前NAT逻辑是以client的OnConnecting连接目的地址
假设有2个目的地址A B,如果中途A掉线再上线无法继续接收数据
在实际的调试的时候,经常会断开A或B,而不能断开client
希望能再优化一下

Nice to meet you

I am Cary,This is my project.I hope it helps you do your job better.

TCPClient类能否增加OnError等回调?

现在集成Touch到Unity客户端。由于异步是多线程报错不会抛出错误日志。也不能try到。需要自己实现一遍一样的异步接口去try捕获异常

CreateExpressionInvoker中的parametersCast的bug!

    protected Func<object, object[], object> CreateExpressionInvoker(MethodInfo method)
    {
        var instance = Expression.Parameter(typeof(object), "instance");
        var parameters = Expression.Parameter(typeof(object[]), "parameters");

        var instanceCast = method.IsStatic ? null : Expression.Convert(instance, method.DeclaringType);
        var parametersCast = method.GetParameters()
                                   .Select((p, i) =>
                                   {
                                       var parameter = Expression.ArrayIndex(parameters, Expression.Constant(i));
                                       return Expression.Convert(parameter, p.ParameterType.GetRefOutType()); // 这里需要使用GetRefOutType(),否则如果rpc函数有ref 参数时,使用表达式树生成代码时会报ByRef错误
                                   });
        var body = Expression.Call(instanceCast, method, parametersCast);

测试HttpService 请求是单线程处理的,并发请求后来的会被阻塞住

HttpService ParseHttpServer = new HttpService();
ParseHttpServer.Setup(new TouchSocketConfig()//加载配置
.SetListenIPHosts(ServerConfig.PraseServerPort)
.ConfigureContainer(a =>
{
a.AddConsoleLogger();
})
.ConfigurePlugins(a =>
{
a.Add<MyHttpPlug_Get>();
a.Add<MyHttpPlug_Post>();
//default插件应该最后添加,其作用是
//1、为找不到的路由返回404
//2、处理header为Option的探视跨域请求。
a.UseDefaultHttpServicePlugin();
}));
ParseHttpServer.Start();

多线程场景下FileStorageReader疑似提前释放资源

作者大佬您好,我遇到的问题是:

我建立了基于TCP协议的服务器和客户端,用于传输文件。因为文件通常很大,因此我使用【Task多线程+FileStorageReader读取文件+分片发送】。
但是,当有多个客户端时,也就是多个Task访问同一个资源,该资源会被提前释放。
也就是说,当有100个客户端,前99个都能正常接收文件,唯独最后1个客户端,在等待文件的最后1个分片时,服务器报错,无法发送,导致客户端无法完成整个文件的接收。

代码如下:

//第一步,用户点击按钮,选择单个文件,服务器负责向所有在线客户端发送

private void button_SendFile_Click(object sender, EventArgs e)
{
          foreach (SocketClient Socket in Server.GetClients())
          {
                  Socket.SendFile(fPath);
          }
}

//第二步,SendFile方法负责建立新的线程,分片发送文件

public void SendFile(string path)
 {
        Task T = new Task(() =>
        {
                byte[] buffer = new byte[1024*64];
                using (var reader = FilePool.GetReader(path))
                {
                        int seq = 0;//文件过大,需要切片发送
                        while (true)
                        {
                                int r = reader.Read(buffer, 0, buffer.Length);
                                if (r == 0) { break; }

                                byte[] packet = new RequestInfo(buffer).BuildAsBytes();
                                base.Send(packet, 0, packet.Length);
                                seq++;
                        }
                        //Thread.Sleep(5000);//如果让每个Task结束发送后都等待一段时间,就不会发生该问题
                }

        }); TStart();
}

用https://www.baidu.com无法获取,用http://www.baidu.com可以获取

HttpClient client = new HttpClient();
client.Setup(new TouchSocketConfig().SetRemoteIPHost(new IPHost("https://www.baidu.com")));
client.Connect();//先做连接
HttpRequest request = new HttpRequest();
request
    .InitHeaders()
    .SetUrl("/")
    .SetHost(client.RemoteIPHost.Host)
    .AsGet();
var respose = client.Request(request, millisecondsTimeout: 1000 * 10);
Console.WriteLine(respose.GetBody());
Console.ReadLine();

异步无法重连

TCPClient使用ConnectAsync连接服务端,服务端立即重启,TCPClient在在断开事件中,再次调用ConnectAsync连接服务端,没有任何反应,无法连接服务端

TCP引用断线重连报错

tcpClient = new TcpClient();
tcpClient.Connected = (client, e) => {
Console.WriteLine($"{DateTime.Now}:中控服务器、连接成功");
};//成功连接到服务器

        tcpClient.Disconnected = (client, e) => {
            Console.WriteLine($"{DateTime.Now}:中控服务器、断开连接");
        };//从服务器断开连接,当连接不成功时不会触发。

        tcpClient.Received = (client, byteBlock, requestInfo) =>
        {

        };

        tcpClient.Setup(new TouchSocketConfig().
            SetRemoteIPHost($"{ip}:{port}").
            ConfigurePlugins((a) =>
        {

            a.UseReconnection(-1, false, 1000 * 5, (e) =>
            {
                Console.WriteLine($"{DateTime.Now}:中控服务器、重新连接成功");
            });

        }));

UseReconnection 这句代码的时候报错。注释掉就没问题了。
SY

我是同时开启了TCP和UDP服务器。不知道跟这个有没有关系。突然报开这个错了。之前是可以运行的。没有进行升级操作

pro1.45 service.IDChanged 不能触发

使用 pro1.45 在 service.Received 里面 使用 service.ResetID(idold, idnew); client.ResetID 修改ID,能够修改成功,但是没有触发 service.IDChanged 调用

    TcpService service = new();
    service.IDChanged = (client, e) =>
    {
        client.Logger.Warning($"{client.GetIPPort()}ID变更: {e.OldID},{e.NewID}");
    };
    service.Received = (client, byteBlock, requestInfo) =>  //从客户端收到信息
    {
        try
        {
            TLVDataFrame buf = (TLVDataFrame)requestInfo;
            if (buf.Tag == 10)
            {
                var idsA = Encoding.UTF8.GetString(buf.Value, 0, buf.Length).SplitFirst('-');
                if (idsA[1] != "0")                          //处理待连接的客户端ID
                {
                    try
                    {
                        var idnew = idsA[1] + "-" + idsA[0];  //待连接的客户端的新ID
                        var idold = client.GetOtherIDs().Single((id) => id.StartsWith(idsA[1] + "-"));      //老ID
                        if (string.IsNullOrEmpty(idold))    //没有找到待连接的客户端
                        {
                            idsA[1] = "0";
                        }
                        else if (idold != idnew)            //待连接的客户端有变动
                        {
                            service.ResetID(idold, idnew);
                            service.Send(idnew, new ValueTLVDataFrame(10, Encoding.UTF8.GetBytes(idnew)));

                            var idsB = idold.SplitFirst('-');
                            if (idsB[1] != "0")             //原先还有连接关系。抢占,需要断开原有关系
                            {
                                idold = idsB[1] + "-" + idsB[0];
                                idnew = idsB[1] + "-0";
                                service.ResetID(idold, idnew);
                                service.Send(idnew, new ValueTLVDataFrame(10, Encoding.UTF8.GetBytes(idnew)));
                            }
                        }
                    }
                    catch
                    {
                        idsA[1] = "0";
                    }
                }

                if (idsA[0] != "0")                 //处理自身的ID关系
                {
                    var idnew = idsA[0] + "-" + idsA[1];
                    var idold = client.ID;
                    client.ResetID(idnew);
                    client.Send(new ValueTLVDataFrame(10, Encoding.UTF8.GetBytes(idnew)));
                    client.Logger.Warning($"{client.GetIPPort()}变更ID:{idnew},在线客户数{service.Count}");

                    var idsC = idold.SplitFirst('-');
                    if (idsC[1] != "0")             //原先还有连接关系。需要放弃,断开原有关系
                    {
                        idold = idsC[1] + "-" + idsC[0];
                        idnew = idsC[1] + "-0";
                        service.ResetID(idold, idnew);
                        service.Send(idnew, new ValueTLVDataFrame(10, Encoding.UTF8.GetBytes(idnew)));
                    }
                }
            }
            else                    //正常需要转发的数据
            {
                var idsD = client.ID.SplitFirst('-');
                if (idsD[1] != "0")
                {
                    var rmid = idsD[1] + "-" + idsD[0];
                    service.Send(rmid, buf);
                    client.Logger.Info($"{client.GetIPPort()} 透传 {rmid},{buf.Tag},{buf.Length}");
                }
            }
        }
        catch (Exception ex)
        {
            client.Logger.Error(ex.ToString());
        }
    };

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.