我正在使用 C++Builder 10.1 Berlin 编写一个简单的 WebSocket 服务器应用程序,它在端口上侦听从 Web 浏览器(如 Google Chrome)发送的一些命令。
在我的表单上,我有一个 TMemo、TButton 和 TIdHTTPServer,并且我有以下代码:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
IdHTTPServer1->Bindings->DefaultPort = 55555;
IdHTTPServer1->Active = true;
}
void __fastcall TForm1::IdHTTPServer1Connect(TIdContext *AContext)
{
Memo1->Lines->Add(AContext->Binding->PeerIP);
Memo1->Lines->Add( AContext->Connection->IOHandler->ReadLn(enUTF8));
Memo1->Lines->Add( AContext->Data->ToString());
}
void __fastcall TForm5::IdHTTPServer1CommandOther(TIdContext *AContext, TIdHTTPRequestInfo *ARequestInfo,
TIdHTTPResponseInfo *AResponseInfo)
{
UnicodeString svk,sValue;
TIdHashSHA1 *FHash;
TMemoryStream *strmRequest;
FHash = new TIdHashSHA1;
strmRequest = new TMemoryStream;
strmRequest->Position = 0;
svk = ARequestInfo->RawHeaders->Values["Sec-WebSocket-Key"];
Memo1->Lines->Add("Get:"+svk);
AResponseInfo->ResponseNo = 101;
AResponseInfo->ResponseText = "Switching Protocols";
AResponseInfo->CloseConnection = False;
//Connection: Upgrade
AResponseInfo->Connection = "Upgrade";
//Upgrade: websocket
AResponseInfo->CustomHeaders->Values["Upgrade"] = "websocket";
sValue = svk + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
sValue = TIdEncoderMIME::EncodeBytes( FHash->HashString(sValue) );
AResponseInfo->CustomHeaders->Values["Sec-WebSocket-Accept"] = sValue;
AResponseInfo->ContentText = "Welcome here!";
AResponseInfo->WriteHeader();
UnicodeString URLstr = "http://"+ARequestInfo->Host+ARequestInfo->Document;
if (ARequestInfo->UnparsedParams != "") URLstr = URLstr+"?"+ARequestInfo->UnparsedParams;
Memo1->Lines->Add(URLstr);
Memo1->Lines->Add(ARequestInfo->Command );
Memo1->Lines->Add("--------");
Memo1->Lines->Add(ARequestInfo->RawHeaders->Text );
Memo1->Lines->Add(AContext->Data->ToString() );
}
在 Chrome 中,我执行以下 Javascript 代码:
var connection = new WebSocket('ws://localhost:55555');
connection.onopen = function () {
connection.send('Ping');
};
但我从 Chrome 收到此错误:
VM77:1 WebSocket 连接到“ws://localhost:55555/”失败:一个或多个保留位打开:reserved1 = 1,reserved2 = 0,reserved3 = 0
我希望 WebSocket 连接成功,然后我可以在 Web 浏览器和我的服务器应用程序之间发送数据。
也许有人已经知道出了什么问题,并且可以展示如何实现这一目标的完整示例?
这是我的应用程序的 Memo1 显示的内容:
192.168.0.25 获取/HTTP/1.1 获取:TnBN9qjOJiwka2eJe7mR0A== http:// 主持人: -------- 连接:升级 Pragma:无缓存 缓存控制:无缓存 升级:websocket 来源:http://bcbjournal.org Sec-WebSocket-版本:13 用户代理:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36 接受编码:gzip、deflate、sdch 接受语言:en-US,en;q=0.8 Sec-WebSocket-Key:TnBN9qjOJiwka2eJe7mR0A== Sec-WebSocket-Extensions:permessage-deflate;client_max_window_bits
以下是 Chrome 显示的内容:
响应请求:
HTTP/1.1 101 交换协议 连接:升级 内容类型:文本/html;字符集=ISO-8859-1 内容长度:13 日期:格林威治标准时间 2017 年 6 月 8 日星期四 15:04:00 升级:websocket Sec-WebSocket-Accept: 2coLmtu++HmyY8PRTNuaR320KPE=
请求标头
获取 ws://192.168.0.25:55555/HTTP/1.1 主机:192.168.0.25:55555 连接:升级 Pragma:无缓存 缓存控制:无缓存 升级:websocket 来源:http://bcbjournal.org Sec-WebSocket-版本:13 用户代理:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36 接受编码:gzip、deflate、sdch 接受语言:en-US,en;q=0.8 Sec-WebSocket-Key:TnBN9qjOJiwka2eJe7mR0A== Sec-WebSocket-Extensions:permessage-deflate;client_max_window_bits