c++ - 使用 C++ 服务器制作 Websocket

标签 c++ sockets websocket

我正在用 C++ 使服务器连接到 WebSocket,但不知何故,它没有连接到 WebSocket。 WebSocket 显示连接已关闭并且 c++ 服务器中也存在一些问题,因为在从 WebSocket 第二次调用服务器时,它显示以下错误 - 双重释放或损坏(out)。我花了很多时间在上面。这是代码: 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 的响应是什么。

最佳答案

这是一个问题(在 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;
}

关于c++ - 使用 C++ 服务器制作 Websocket,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9860041/

相关文章:

java - Java 中的 IP header

JavaFX 和套接字 = 不在 FX 应用程序线程上

websocket - 如何使用 Chrome 开发者工具检查 websocket 流量?

c++ - 从 C++ 设置变量时 QML 内存泄漏

android - 通过热点在两个 Android 设备之间进行数据交换

javascript - socket.io 在连接时发出

javascript - Safari 中的数据 URI 泄漏(原为 : Memory Leak with HTML5 canvas)

c++ - 临时元素的保存期限有什么要求?

c++ - pugixml 与 tinyxml

c++ - 文件即使存在也打不开