C# TcpListener写入ClientWebSocket

C# TcpListener写入ClientWebSocket,c#,websocket,tcplistener,C#,Websocket,Tcplistener,我目前正在创建一个将在浏览器中运行的项目,并连接了一个c#server 服务器使用TcpListener来接受连接和接收消息,但我希望服务器能够响应客户端。这给了我一些问题 以下是我的客户的代码: private ClientWebSocket socket; internal async Task InitAsync(string host, int port, GamePacketParser parser) { Lo

我目前正在创建一个将在浏览器中运行的项目,并连接了一个c#server

服务器使用TcpListener来接受连接和接收消息,但我希望服务器能够响应客户端。这给了我一些问题

以下是我的客户的代码:

        private ClientWebSocket socket;

        internal async Task InitAsync(string host, int port, GamePacketParser parser)
        {
            Logger.Info("Setting up the socket connection...");

            socket = new ClientWebSocket();
            await socket.ConnectAsync(new Uri($"ws://{host}:{port}/"), CancellationToken.None);

            Logger.Info("Successfully established the connection.");
            this.parser = parser;
            buffer = new byte[GameSocketManagerStatics.BUFFER_SIZE];

            Task.Run(recieve);
        }

        private async Task recieve()
        {
            Logger.Debug("Starting Reciever.....");
            var result = await socket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);

            var packet = new byte[result.Count];
            Array.Copy(buffer, packet, result.Count);

            ///parser.handlePacketData(packet);

            Logger.Debug($"Recieved: {Encoding.UTF8.GetString(packet)}");
            ///Task.Run(recieve); //Start receiving again
        }

        public async Task SendData(byte[] data)
        {
            Logger.Debug("Triggerd send");
            string packet = BitConverter.ToString(data);
            await socket.SendAsync(new ArraySegment<byte>(data), WebSocketMessageType.Text, true, CancellationToken.None);
            Logger.Info($"Sended Data: {packet}");
        }


问题可能是因为它不是为WebSocket编码的,但我尝试了许多在线编码解决方案(例如:),但即使使用这些编码器,似乎也没有解决问题


提前谢谢你的帮助。我对WebSockets还是新手,所以可以用勺子喂食。

aepot你的答案很好,但我真的希望我的服务器是TCP级别的,如果我想在使用sockets的官方服务器上使用它,我需要更改很多代码

我对WebSocket做了更多的挖掘,经过一些搜索后我发现,我基本上需要在发送数据之前发送一个标题。我不知道如何创建该标题,但我在网上找到了一些这样做的代码。(我已经搜索了大约12个小时:?)

解决方案:

        protected int GetHeader(bool finalFrame, bool contFrame)
        {
            int header = finalFrame ? 1 : 0;//fin: 0 = more frames, 1 = final frame
            header = (header << 1) + 0;//rsv1
            header = (header << 1) + 0;//rsv2
            header = (header << 1) + 0;//rsv3
            header = (header << 4) + (contFrame ? 0 : 1);//opcode : 0 = continuation frame, 1 = text
            header = (header << 1) + 0;//mask: server -> client = no mask

            return header;
        }


        protected byte[] IntToByteArray(ushort value)
        {
            var ary = BitConverter.GetBytes(value);
            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse(ary);
            }

            return ary;
        }

        public static IEnumerable<string> SplitInGroups(this string original, int size)
        {
            var p = 0;
            var l = original.Length;
            while (l - p > size)
            {
                yield return original.Substring(p, size);
                p += size;
            }
            yield return original.Substring(p);
        }
protectedintgetheader(bool finalFrame,bool contFrame)
{
int header=finalFrame?1:0;//fin:0=更多帧,1=最终帧

header=(服务器不应该从套接字读取header吗?读取对服务器来说效果很好。读取在客户端不起作用。当服务器写入客户端时,客户端ReceiveAsync()将阻止SendAsync(),因为它已接收到一些数据,但无法成功读取数据。
        protected int GetHeader(bool finalFrame, bool contFrame)
        {
            int header = finalFrame ? 1 : 0;//fin: 0 = more frames, 1 = final frame
            header = (header << 1) + 0;//rsv1
            header = (header << 1) + 0;//rsv2
            header = (header << 1) + 0;//rsv3
            header = (header << 4) + (contFrame ? 0 : 1);//opcode : 0 = continuation frame, 1 = text
            header = (header << 1) + 0;//mask: server -> client = no mask

            return header;
        }


        protected byte[] IntToByteArray(ushort value)
        {
            var ary = BitConverter.GetBytes(value);
            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse(ary);
            }

            return ary;
        }

        public static IEnumerable<string> SplitInGroups(this string original, int size)
        {
            var p = 0;
            var l = original.Length;
            while (l - p > size)
            {
                yield return original.Substring(p, size);
                p += size;
            }
            yield return original.Substring(p);
        }
public static void SendMessage(string packet) {
   Queue<string> que = new Queue<string>(packet.SplitInGroups(125)); //Make it so the message is never longer then 125 (Split the message into parts & store them in a queue)
   int len = que.Count;

   while (que.Count > 0)
   {
      var header = GetHeader(
         que.Count > 1 ? false : true,
         que.Count == len ? false : true
      ); //Get the header for a part of the queue

      byte[] list = Encoding.UTF8.GetBytes(qui.Dequeue()); //Get part of the message out of the queue
      header = (header << 7) + list.Length; //Add the length of the part we are going to send

      //Send the header & message to client
      stream.write(IntToByteArray((ushort)header));
      stream.write(list);
   }
}