使用 c++ 服务器制作 Websocket
Posted
技术标签:
【中文标题】使用 c++ 服务器制作 Websocket【英文标题】:making the Websocket using the c++ server 【发布时间】:2012-03-25 12:17:41 【问题描述】:我正在用 C++ 制作服务器以连接到 WebSocket,但不知何故,它没有与 WebSocket 连接。 WebSocket 显示连接已关闭,并且 c++ 服务器中也存在一些问题,如从 WebSocket 对服务器的第二次调用,它显示以下错误 - 双重释放或损坏(输出)。我花了很多时间。这是代码: c++
#include<iostream>
#include <string>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
using namespace std;
string getConnectionKey(char*);
void acceptConnection(int, const char*);
void readConnection(int);
void bail(char*);
string executeShellCommand(const string&);
string getBase64Encoded(string);
char *getClientKey(char*);
string getSHA1Hash(string);
int main()
char srvr_adr[] = "127.0.0.1";
char srvr_port[] = "9099";
struct sockaddr_in adr_srvr;
struct sockaddr_in adr_clnt;
socklen_t len_inet;
int s; // Server Socket
int c; // Client Socket
int z;
char *data;
char readdata[256];
int count = 2;
data = (char*)malloc(sizeof(char)*128);
s = socket(PF_INET, SOCK_STREAM, 0);
if(s == -1)
bail("socket()");
memset(&adr_srvr,0,sizeof(adr_srvr));
adr_srvr.sin_family = AF_INET;
adr_srvr.sin_port = htons(atoi(srvr_port));
if( strcmp(srvr_adr,"*")!=0)
adr_srvr.sin_addr.s_addr = inet_addr(srvr_adr);
if(adr_srvr.sin_addr.s_addr == INADDR_NONE)
bail(" INVALID ADRESS \n");
else /* WILD ADDRESS*/
adr_srvr.sin_addr.s_addr = INADDR_ANY;
len_inet = sizeof adr_srvr;
z = bind(s,(struct sockaddr*)&adr_srvr, len_inet);
if(z==-1)
bail("bind(2)");
z = listen(s,10);
if(z==-1)
bail("listen(2)");
for(;;)
len_inet = sizeof(adr_clnt);
c = accept(s, (struct sockaddr*)&adr_clnt,&len_inet);
if(c==-1)
bail("accept(2)");
readConnection(c);
close(c);
return 0;
void readConnection(int c)
int z;
char readdata[256];
// READING
z = read(c,readdata, sizeof(readdata)-1);
if(z==-1)
bail("read(2)");
else if(strlen(readdata)>0)
printf(" READ \n%s\n", readdata);
string key = getConnectionKey(readdata);
cout<<" KEY "<<key<<endl;
acceptConnection(c, key.c_str());
void acceptConnection(int c, const char *key)
int z;
char response[] = "HTTP/1.1 101 Switching Protocols\nUpgrade: websocket\nConnection: Upgrade\nSec-WebSocket-Accept: ";
char *output;
output = (char*)malloc( sizeof(char) * ( strlen(key) + strlen(response) + 1) );
strcat(output, response);
strcat(output, key);
cout<<" output "<<output<<endl;
// WRITING
z = write(c, output, strlen(output));
if(z == -1)
bail("write(2)");
printf(" Connection Done \n");
string getConnectionKey(char *str)
char *start,*end,*key;
int len;
string s("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
// GET CLIENT KEY
key = getClientKey(str);
// Appending the key
s = key + s;
// SHA1 HASH
string out = getSHA1Hash(s);
//hashwrapper *h = new sha1wrapper();
//string out = h->getHashFromString(s);
// BASE 64 ENCODING
string encoded = getBase64Encoded(out);
//encoded = (char*)malloc(sizeof(char)*256);
//strcpy(encoded, getBase64Encoded(out) );
free(key);
//delete h;
return encoded;
char *getClientKey(char *str)
int len;
char *start,*end,*key;
start = strstr(str, "Sec-WebSocket-Key:");
if(start == NULL)
return false;
start += 17;
end = strstr(start, "==");
if(end == NULL)
return false;
end++;
while( !(*start>=65 && *start<=90 || *start >= 97 && *start<=122 || *start>=48 && *start<=57 || *start == '+' || *start=='/') )
start++;
len = end - start + 1;
key = (char*) malloc( sizeof(char) * (len+1) );
strncpy(key,start,len);
return key;
string getBase64Encoded(string s)
int len;
string str="";
len = s.length();
char *command;
for(int i=len-1 ; i>=1; i=i-2)
str = s.substr(i-1,2) + str;
str = "\\x" + str;
if(len%2==1)
str = s[0] + str;
str = "\\x" + str;
// making the command to be send to shell
str = "printf \"" + str ;
str = str + "\" | base64";
cout<<endl<<" STRING "<<str<<endl;
return executeShellCommand(str);
string getSHA1Hash(string str)
int len ;
string output;
str = "printf \""+str;
str = str +"\" | sha1sum";
cout<<str<<endl;
output = executeShellCommand(str);
return output.substr(0,output.length()-4);;
string executeShellCommand(const string& cmd)
FILE *fpipe;
if ( !(fpipe = (FILE*)popen(cmd.c_str(),"r")) )
// If fpipe is NULL
perror("Problems with pipe");
exit(1);
char buf[256] = "";
string line="";
while ( fgets( buf, sizeof buf, fpipe) )
if(strlen(buf)>0)
line.append(buf);
memset(buf, 0, sizeof(buf));
// CLOSE THE PIPE
pclose(fpipe);
return line;
void bail(char *on_what)
if(errno!=0)
fputs( strerror(errno), stderr);
fputs( ":", stderr);
fputs( on_what, stderr);
fputs("\n",stderr);
这是 Websocket 代码:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>WebSocket Chat</title>
</head>
<body>
<h1>WebSocket Chat</h1>
<section id="content"></section>
<input id="message" type="text" tabindex="1"/>
<textarea id="show">
</textarea>
<script src="http://www.google.com/jsapi"></script>
<script>google.load("jquery", "1.3")</script>
<script src="http://jquery-json.googlecode.com/files/jquery.json-2.2.min.js"></script>
<!--script src="http://jquery-websocket.googlecode.com/files/jquery.websocket-0.0.1.js"></script-->
<script src="/js/jquery.websocket-0.0.1.js"></script>
<script type="text/javascript">
/*var ws = $.websocket("ws://127.0.0.1:9099/",
events:
message: function(e)
alert("e.data");
$('#content').append(e.data + '<br>')
);*/
var websocketConnection = new WebSocket("ws://127.0.0.1:9099/");
websocketConnection.onopen = function(ev)
showmsg('Connected to the echo service');
;
websocketConnection.onerror = function(ev)
showmsg(" ERROR : ".ev.data);
websocketConnection.onclose = function(ev)
showmsg(" Connection Closed");
;
websocketConnection.onmessage = function(event)
showmsg(event.data);
$('#content').append(event.data+"<br>");
;
showmsg(" CURRENT STATE "+websocketConnection.readyState);
if(!websocketConnection)
showmsg(" object null ");
websocketConnection.send("Hello Echo Server");
$('#message').change(function()
flag = ws.send('message', this.value);
if(!flag)
alert("not send");
this.value = '';
);
function showmsg(content)
$('#show').val(content+"<br>");
</script>
</body>
</html>
请帮帮我,C++ 中的问题是什么以及要发送到 WebScoket 的响应是什么。
【问题讨论】:
【参考方案1】:这是一个问题(在executeShellCommand()
函数中):
command = (char*) malloc( sizeof(char) * cmd.length() );
line = (char*)malloc(sizeof(char)*256);
line[0] = '\0';
//cout<<" COMMAND "<<cmd<<endl;
strcpy(command, cmd.c_str() ); // Writes one beyond the end of the
// 'command' buffer as no space allocated
// for null terminator
您可以将cmd.c_str()
直接传递给popen()
,而不是为此目的分配和填充command
缓冲区:
if ( !(fpipe = (FILE*)popen(cmd.c_str(),"r")) )
我建议在可能的情况下将char*
替换为std::string
,并允许它为您管理内存并在std::string
不合适时使用堆栈分配的缓冲区而不是动态分配缓冲区。例如:
std::string executeShellCommand(const std::string& cmd)
FILE *fpipe;
if ( !(fpipe = (FILE*)popen(cmd.c_str(),"r")) )
// If fpipe is NULL
perror("Problems with pipe");
exit(1);
char buf[256] = "";
std::string line;
while ( fgets( buf, sizeof buf, fpipe) )
line += buf;
memset(buf, 0, sizeof(buf));
// CLOSE THE PIPE
pclose(fpipe);
return line;
【讨论】:
仍然无法正常工作。在网络套接字的第二次,它在 line+=buf 处给出内存损坏错误。为什么我发送的密钥正确时正在建立 websocket 连接。以上是关于使用 c++ 服务器制作 Websocket的主要内容,如果未能解决你的问题,请参考以下文章
使用 ClientWebSocket .net 核心测试 TestHost.WebSocketClient
用Wix手工编辑XML制作C++ MSI安装程序,怎样保证安装新版本时候强制卸载旧版本,急急急!!!
如何使用 OpenCV 从 C++ 程序制作 Android 应用程序