c++websocketサービス側とJavaScript通信を実現
22392 ワード
c++websocketサービス側とJavaScript通信を実現
次の点に注意してください.まずwebsocketとは何かを理解し、ここでは について説明しない. websocketのインタラクティブプロトコル を明確にする
目次 c websocketサービス側とJavaScript通信を実現 ディレクトリ 握手プロトコルとプロトコルの解析 まず普通のsocket を建てに来ました二握手プロトコル 3ワークスレッドクライアント応答情報を処理するバイトコード 4最後に応答クライアント 5最後に応答クライアント
握手プロトコルとプロトコルの解析
多くの資料にwebsocketの握手プロトコルが詳しく紹介されていますが、ここではあまり言わないで、直接コードをつけましょう.
一、まず普通のsocketを建てる
二、握手協議
三、作業スレッドはクライアント応答情報のバイトコードを処理する
四、最後にクライアントに応答する
五、最後にクライアントに応答する
非常に簡単なテストコード
次の点に注意してください.
目次
[TOC]
を使用してディレクトリを生成します.握手プロトコルとプロトコルの解析
多くの資料にwebsocketの握手プロトコルが詳しく紹介されていますが、ここではあまり言わないで、直接コードをつけましょう.
一、まず普通のsocketを建てる
void Initsocket(){
WORD imgrequest;
WSADATA wsadata;
imgrequest = MAKEWORD(1, 1);
int err;
err = WSAStartup(imgrequest, &wsadata);
if (!err){
printf("
");
}else{
printf("
");
return;
}
SOCKET sersocket = socket(AF_INET, SOCK_STREAM, 0);
SOCKADDR_IN addr;
addr.sin_family = AF_INET;
addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //ip
addr.sin_port = htons(8899); //
bind(sersocket, (SOCKADDR*)&addr, sizeof(SOCKADDR));//
listen(sersocket, 10); //
SOCKADDR_IN clientsocket;
int len = sizeof(SOCKADDR);
boolean isConnected = false;
int i = 0;
while (true){
SOCKET serConn = accept(sersocket, (SOCKADDR*)&clientsocket, &len);
printf("
");
//
HANDLE hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WorkThread, (LPVOID)serConn, 0, 0);
if (hThread1 != NULL)
{
CloseHandle(hThread1);
}
Sleep(1000);
closesocket(serConn);
}
}
二、握手協議
/* key */
void requestInfo(SOCKET sockClient, char * request){
char recev[1024] = "";
recv(sockClient, recev, 2048, 0);
//cout << recev << endl;
string s = recev;
int i = s.find("Sec-WebSocket-Key");
s = s.substr(i + 19, 24);
// key, key
//
getKey(request,s);
}
/*
key sha ,
*/
void getKey(char *request, string clientkey){
strcat(request, "HTTP/1.1 101 Switching Protocols\r
");
strcat(request, "Connection: upgrade\r
");
strcat(request, "Sec-WebSocket-Accept: ");
string server_key = clientkey;
server_key += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
SHA1 sha;
unsigned int message_digest[5];
cout <<"server_key:"<< server_key << endl;
sha.Reset();
sha << server_key.c_str();
sha.Result(message_digest);
for (int i = 0; i < 5; i++) {
message_digest[i] = htonl(message_digest[i]);
}
server_key = base64_encode(reinterpret_cast<const unsigned char*>(message_digest), 20);
server_key += "\r
";
strcat(request, server_key.c_str());
strcat(request, "Upgrade: websocket\r
\r
");
cout << "shalserver_key:" << server_key << endl;
}
三、作業スレッドはクライアント応答情報のバイトコードを処理する
/* */
void WorkThread(SOCKET sockClient){
char request[1024] = ""; //
char clieninfo[2048]= ""; //
int len = 0; //
int point = 0; //
int tmppoint = 0; //
//
requestInfo(sockClient, request);
respondInfo(sockClient, request);
//
// , ,
// ,
//
len=recv(sockClient, clieninfo, 2048, 0);
string ss = clieninfo;
cout << "
:"<" :"<< ss << endl;
if (len>0){
/* b , point , , */
byte b[4096] = "";
//
memcpy(b, clieninfo, 2048);
cout << " :" << b << endl;
for (int i = 0; i <= 33; i++){
printf("%d\t", b[i]);
}
printf("
");
//
int first = b[point] & 0xFF;
printf(" :%d,%d,%d
", point, b[point], first);
byte opCode = (byte)(first & 0x0F); //0000 1111 opCode 00001111
if (opCode == 8){
closesocket(sockClient);
}
//
first = b[++point];
//
int payloadLength = first & 0x7F;
printf(" :%d,[%d],%d
", point, b[point], payloadLength);
if (payloadLength == 126) {
byte extended[2] = "";
extended[0] = b[++point];
extended[1] = b[++point];
int shift = 0;
payloadLength = 0;
for (int i = 2- 1; i >= 0; i--) {
payloadLength = payloadLength + ((extended[i] & 0xFF) << shift);
shift += 8;
}
}else if (payloadLength == 127) {
byte extended[8] = "";
tmppoint = ++point; //
point = --point;
for (int i = 0; i < 8;i++){
extended[i] = b[tmppoint + i];
point++;
}
int shift = 0;
payloadLength = 0;
for (int i = 8 - 1; i >= 0; i--) {
payloadLength = payloadLength + ((extended[i] & 0xFF) << shift);
shift += 8;
}
}
// 126 127
if ((payloadLength != 126) || (payloadLength != 127)){
point = 1;
}
cout << " :" << payloadLength << endl;
// ,
byte mask[4] = "";
tmppoint = ++point;
// ,
point = --point;
//
for (int i = 0; i < 4; i++){
mask[i] = b[tmppoint + i];
point++;
printf(" mask :%d,[%d],%d\t
", point, mask[i], payloadLength);
}
byte changeb[4096] = "";
// ,
int length = payloadLength;
int readThisFragment = 1;
//
while (payloadLength > 0){
int maskbyte = b[++point];
int index = (readThisFragment - 1) % 4;
maskbyte = maskbyte ^ (mask[index] & 0xFF);
changeb[readThisFragment-1] = (byte)maskbyte;
printf(" :%d,[%d],%d
", point, maskbyte, readThisFragment);
payloadLength--;
readThisFragment++;
}
char a[4096] = "1231";
byte test[1024] = "";
memcpy(test, a, strlen(a));
Sleep(5000);//
//
//respondClient(sockClient, changeb, length, true);
respondClient(sockClient, test, strlen(a), true);
//
char charb[4096] = "";
memcpy(charb, changeb, length);
//charb[length] = 0;
for (int i = 0; i < length;i++){
printf("%d\t", charb[i]);
}
printf("%d
");
string s = charb;
cout << " :" << s << endl;
//closesocket(sockClient);
}
}
/* */
void respondInfo(SOCKET sockClient, char * request){
send(sockClient, request, strlen(request), 0);
}
四、最後にクライアントに応答する
/* , */
void respondClient(SOCKET sockClient, byte charb[],int length, boolean finalFragment){
byte buf[1024] = "";
int first = 0x00;
int tmp = 0;
if (finalFragment) {
first = first + 0x80;
first = first + 0x1;
}
buf[0] = first;
tmp = 1;
cout <<" :"<< length << endl;
unsigned int nuNum = (unsigned)length;
if (length < 126) {
buf[1] = length;
tmp = 2;
}else if (length < 65536) {
buf[1] = 126;
buf[2] = nuNum >> 8;
buf[3] = length & 0xFF;
tmp = 4;
}else {
// 65536
buf[1] = 127;
buf[2] = 0;
buf[3] = 0;
buf[4] = 0;
buf[5] = 0;
buf[6] = nuNum >> 24;
buf[7] = nuNum >> 16;
buf[8] = nuNum >> 8;
buf[9] = nuNum & 0xFF;
tmp = 10;
}
for (int i = 0; i < length;i++){
buf[tmp+i]= charb[i];
printf(" :%d
", charb[i]);
}
char charbuf[1024] = "";
memcpy(charbuf, buf, length + tmp);
send(sockClient, charbuf, 1024, 0);
}
五、最後にクライアントに応答する
非常に簡単なテストコード
(function(){
var $ = function(id){return document.getElementById(id) || null;}
var wsServer = 'ws://127.0.0.1:8080';
var ws = new WebSocket(wsServer);
var isConnect = false;
ws.onopen = function (evt) { onOpen(evt) };
ws.onclose = function (evt) { onClose(evt) };
ws.onmessage = function (evt) { onMessage(evt) };
ws.onerror = function (evt) { onError(evt) };
function onOpen(evt) {
console.log(" ");
isConnect = true;
}
function onClose(evt) {
//console.log("Disconnected");
}
function onMessage(evt) {
console.log('Retrieved data from server: ' + evt.data);
}
function onError(evt) {
//console.log('Error occured: ' + evt.data);
}
function sendMsg() {
if(isConnect){
ws.send('hello');
}
}
})();