zoukankan      html  css  js  c++  java
  • mormot websocket

    mormot websocket

    THttpApiWebSocketServer基于http.sys通讯的websocket server,同时它又能作为普通的http server使用,支持高并发。

    下面是它的演示代码:

    program Project31WinHTTPEchoServer;
    
    {$I Synopse.inc}
    
    {$APPTYPE CONSOLE}
    
    uses
      {$I SynDprUses.inc} // use FastMM4 on older Delphi, or set FPC threads
      SysUtils,
      SynZip,
      SynCrtSock,
      SynCommons,
      SynTable;
    
    type
      TSimpleWebsocketServer = class
      private
        fServer: THttpApiWebSocketServer;
    //    fProtocols: THttpApiWebSocketServerProtocolDynArray;
        function onHttpRequest(Ctxt: THttpServerRequest): cardinal;
        function onAccept(Ctxt: THttpServerRequest; var Conn: THttpApiWebSocketConnection): Boolean;
        procedure onConnect(const Conn: THttpApiWebSocketConnection );
        procedure onMessage(const Conn: THttpApiWebSocketConnection; aBufferType: WEB_SOCKET_BUFFER_TYPE; aBuffer: Pointer; aBufferSize: Cardinal);
        procedure onDisconnect(const Conn: THttpApiWebSocketConnection ; aStatus: WEB_SOCKET_CLOSE_STATUS; aBuffer: Pointer; aBufferSize: Cardinal);
      public
        constructor Create;
        destructor Destroy; override;
      end;
    { TSimpleWebsocketServer }
    
    constructor TSimpleWebsocketServer.Create;
    begin
      fServer := THttpApiWebSocketServer.Create(false, 8, 10000);
      fServer.AddUrl('','8888', False, 'localhost');
      fServer.AddUrlWebSocket('whatever', '8888', False, 'localhost');
      // ManualFragmentManagement = false - so Server will join all packet fragments
      // automatically and call onMessage with full message content
      fServer.RegisterProtocol('meow', False, onAccept, onMessage, onConnect, onDisconnect);
      fServer.RegisterCompress(CompressDeflate);
      fServer.OnRequest := onHttpRequest;
      fServer.Clone(8);
    end;
    
    destructor TSimpleWebsocketServer.Destroy;
    begin
      fServer.Free;
      inherited;
    end;
    
    function TSimpleWebsocketServer.onAccept(Ctxt: THttpServerRequest; var Conn: THttpApiWebSocketConnection): Boolean;
    begin
    // You can check some Ctxt parameters here
      Result := true;
    end;
    
    procedure TSimpleWebsocketServer.onConnect(const Conn: THttpApiWebSocketConnection);
    begin
      Writeln('New connection. Assigned connectionID=', Conn.index);
    end;
    
    procedure TSimpleWebsocketServer.onDisconnect(const Conn: THttpApiWebSocketConnection;
      aStatus: WEB_SOCKET_CLOSE_STATUS; aBuffer: Pointer; aBufferSize: Cardinal);
    var
      str: RawUTF8;
    begin
      SetString(str, pUtf8Char(aBuffer), aBufferSize);
    
      Writeln('Disconnected ', Conn.index,' ',aStatus,' ',str);
    end;
    
    function TSimpleWebsocketServer.onHttpRequest(Ctxt: THttpServerRequest): cardinal;
    begin
      Writeln('HTTP request to ', Ctxt.URL);
      if Ctxt.URL = '/' then
        Ctxt.OutContent := 'Project31SimpleEchoServer.html'
      else if Ctxt.URL = '/favicon.ico' then
         Ctxt.OutContent := 'favicon.ico';
      Ctxt.OutContentType := HTTP_RESP_STATICFILE;
      Result := 200;
    end;
    
    procedure TSimpleWebsocketServer.onMessage(const Conn: THttpApiWebSocketConnection;
      aBufferType: WEB_SOCKET_BUFFER_TYPE; aBuffer: Pointer; aBufferSize: Cardinal);
    var
      str: RawUTF8;
    begin
      Conn.Send(aBufferType, aBuffer, aBufferSize);
    //  Conn.Protocol.Send(Conn.index, aBufferType, aBuffer, aBufferSize); //also work
      SetString(str, pUtf8Char(aBuffer), aBufferSize);
      if aBufferType = WEB_SOCKET_UTF8_MESSAGE_BUFFER_TYPE then
        Writeln('UTF8 message from ', Conn.index, ': ',str)
      else if aBufferType = WEB_SOCKET_UTF8_FRAGMENT_BUFFER_TYPE then
        Writeln('UTF8 fragment from ', Conn.index, ': ',str)
      else if (aBufferType = WEB_SOCKET_BINARY_MESSAGE_BUFFER_TYPE)
        or (aBufferType = WEB_SOCKET_BINARY_FRAGMENT_BUFFER_TYPE) then
        Writeln(aBufferType, ' from ', Conn.index, ' of length ', aBufferSize)
      else begin
        Writeln(aBufferType, ' from ', Conn.index, ': ',str);
      end;
    end;
    
    var
      _Server: TSimpleWebsocketServer;
      s: string;
      idx: integer;
      MsgBuffer: RawUTF8;
      CloseReasonBuffer: RawUTF8;
    begin
      MsgBuffer := '';
      CloseReasonBuffer := 'Connection closed by server';
      try
        _Server := TSimpleWebsocketServer.Create;
        try
          Writeln('WebSocket server is now listen on ws://localhost:8888/whatever');
          Writeln('HTTP server is now listen on http://localhost:8888/');
          Writeln(' Point your browser to http://localhost:8888/ for initial page');
          WriteLn('Type one of a commnad:');
          Writeln(' - "close connectionID" to close existing webSocket connection');
          Writeln(' - "sendto connectionID" to send text to specified WebCocket');
          Writeln(' - "sendall" to send text to specified WebCocket');
          Writeln(' - press [Enter] to quit');
          Writeln('Waiting for command:');
          repeat
            Readln(s);
            if Pos('close ', s) = 1 then begin
              s := SysUtils.Trim(Copy(s, 7, Length(s)));
              _Server.fServer.Protocols[0].Close(StrToIntDef(s, -1), WEB_SOCKET_SUCCESS_CLOSE_STATUS,
                Pointer(CloseReasonBuffer), length(CloseReasonBuffer));
            end else if Pos('sendto ', s) = 1 then begin
              s := SysUtils.Trim(Copy(s, 8, Length(s)));
              idx := StrToIntDef(s, -1);
              if (idx = -1 ) then
                Writeln('Invalid connection ID. Usage: send connectionID (Example: send 0)')
              else begin
                Write('Type text to send: ');
                Readln(MsgBuffer);
                if _Server.fServer.Protocols[0].Send(
                  StrToIntDef(s, -1), WEB_SOCKET_UTF8_MESSAGE_BUFFER_TYPE,
                  Pointer(MsgBuffer), length(MsgBuffer)
                ) then
                  WriteLn('Sent successfully. The message should appear in the client. Waiting for command:')
                else
                  WriteLn('Error')
              end;
            end else if (s = 'sendall') then begin
              Write('Type text to send: ');
              Readln(MsgBuffer);
              if _Server.fServer.Protocols[0].Broadcast(
                WEB_SOCKET_UTF8_MESSAGE_BUFFER_TYPE,
                Pointer(MsgBuffer), length(MsgBuffer)
              ) then
                WriteLn('Broadcast successfully. All clients should got a message. Waiting for command:')
              else
                WriteLn('Error')
            end else if (s <> '') then
              WriteLn('Invalid comand; Valid command are: close, sendto, sendall');
          until s = '';
        finally
          _Server.Free;
        end;
      except
        on E: Exception do
          Writeln(E.ClassName, ': ', E.Message);
      end;
    end.
    

      

  • 相关阅读:
    Python 类中方法的内部变量,命名加'self.'变成 self.xxx 和不加直接 xxx 的区别
    用foreach遍历 datagridView 指定列所有的内容
    treeView1.SelectedNode.Level
    YES NO 上一个 下一个
    正则 单词全字匹配查找 reg 边界查找 精确匹配 只匹配字符 不含连续的字符
    抓取2个字符串中间的字符串
    sqlite 60000行 插入到数据库只用不到2秒
    将多行文本以单行的格式保存起来 读和写 ini
    将秒转换成时间格式
    richtextbox Ctrl+V只粘贴纯文本格式
  • 原文地址:https://www.cnblogs.com/hnxxcxg/p/12597182.html
Copyright © 2011-2022 走看看