2011-03-15 29 views
0

嗨我試圖使用glib API實現WebSocket服務器。服務器與客戶端(Chrome瀏覽器)成功握手和發送消息。我使用socket.close()斷開與客戶端的連接後出現問題,然後嘗試重新連接。服務器然後在g_io_channel_unix_new()調用中崩潰。這是用於偵聽來自新客戶端的數據的通道。我試着去掉了最後一次使用過的客戶端的io_channel,但沒有任何幫助。有人可以在這個問題上提出一些看法。下面是相關的代碼當客戶端嘗試重新建立連接時,g_io_channel_unix_new()調用SIGSEGV的結果

  gboolean 
      read_socket (GIOChannel *in, GIOCondition condition, gpointer data) 
      { 
       gint got=0, ret=0; 
       char message[256]={'\0'}; 

       char *handShakeReply = NULL, *reply = NULL; 
       char *p=NULL; 
       HandshakeParams hsParams; 
       unsigned long key1=0, key2=0; 
       unsigned char resultKey[16]={'\0'}; 

       gint local_client_socket = g_io_channel_unix_get_fd(in); 

       if(condition & G_IO_HUP) 
       { 
        printf("\nUnexpected Broken pipe error on client_fd\n"); 
        close(local_client_socket); 
        return FALSE; 
       } 


       memset(message,0,256); 
       memset(&hsParams, 0, sizeof(HandshakeParams)); 

       if(isHandShakeDone==0) 
       { 
       printf("\nHandshaking..\n"); 

       got = recv (local_client_socket, message, 256, 0); 

        if (got < 0) 
       { 
         printf("Failed to read from socket"); 
         /*TRUE becasue we still want GmainLoop to monitor this eventsource, the socket*/ 
         return TRUE; 
       } 

       printf("GOT MESSAGE:\n%s\n", message); 

       collect_handshake_params(message, &hsParams); 

       handShakeReply = (char*)malloc(1024); 
       memset(handShakeReply, 0, 1024); 
       p = handShakeReply; 

       strcpy(p, "HTTP/1.1 101 WebSocket Protocol Handshake\x0d\x0a"); 
       p += strlen("HTTP/1.1 101 WebSocket Protocol Handshake\x0d\x0a"); 
       strcpy(p, "Upgrade: WebSocket\x0d\x0a"); 
       p += strlen("Upgrade: WebSocket\x0d\x0a"); 
       strcpy(p, "Connection: Upgrade\x0d\x0a"); 
       p += strlen("Connection: Upgrade\x0d\x0a"); 
       strcpy(p, "Sec-WebSocket-Origin: "); 
       p += strlen("Sec-WebSocket-Origin: "); 
       strcpy(p, hsParams.origin); 
       p += strlen(hsParams.origin); 
       strcpy(p, "\x0d\x0aSec-WebSocket-Location: ws://"); 
       p += strlen("\x0d\x0aSec-WebSocket-Location: ws://"); 
       strcpy(p, hsParams.host); 
       p += strlen(hsParams.host); 
       strcpy(p, "/mySession\x0d\x0a"); 
       p += strlen("/mySession\x0d\x0a"); 
       strcpy(p, "\x0d\x0a"); 
       p += strlen("\x0d\x0a"); 



       if((ret=interpret_key(hsParams.key1,&key1)) < 0) 
        { 
       printf("\nError in parsing key1! Errcode=%d\n",ret); 
       return FALSE; 
        } 
        else 
        { 
       printf("\nStripped Key1 = %ld\n", key1); 
        } 

        if((ret=interpret_key(hsParams.key2,&key2)) < 0) 
        { 
       printf("\nError in parsing key2! Errcode=%d\n",ret); 
       return FALSE; 
        } 
        else 
        { 
       printf("\nStripped Key2 = %ld\n", key2); 
        } 

        //Arrange in Network Byte Order! 
        resultKey[0] = key1 >> 24; 
        resultKey[1] = key1 >> 16; 
        resultKey[2] = key1 >> 8; 
        resultKey[3] = key1; 
        resultKey[4] = key2 >> 24; 
        resultKey[5] = key2 >> 16; 
        resultKey[6] = key2 >> 8; 
        resultKey[7] = key2; 

        memcpy(&resultKey[8], hsParams.key3, 8); 

        copyMD5Hash(resultKey, (unsigned char *)p); 
        p += 16; 

        printf("\nHandshake Reply:\n%s\n", handShakeReply); 

        ret = send(local_client_socket, handShakeReply, p-handShakeReply, 0); 
        if(ret < 0) 
        { 
       perror("\nError in sending handshake reply:"); 
        } 
        else 
        { 
       isHandShakeDone=1; 
        } 

        free(handShakeReply); 
        p=NULL; 
        free_handshake_params(&hsParams); 

       } 
       else 
       { 
        printf("\nServing Client..\n"); 

        getClientRequest(local_client_socket, message); 

        if(message[0] == '\0') 
        { 
        /*Close this connection for this client instance and wait for connection from the next instance of client*/ 

        close(local_client_socket); 

      #if 0 
        GIOStatus status;   
        GError *error=NULL; 

        status = g_io_channel_shutdown(in,TRUE,&error); 
        if(status==G_IO_STATUS_NORMAL) 
        { 
        printf("\nClient IO channel shutdown was normal\n"); 
        } 
        else 
        { 
        printf("\nIO channel shutdown status: %d\n", status); 
        } 


        /*Unref twice since g_io_add_watch() increases the reference count too*/ 
        g_io_channel_unref(in); 
        g_io_channel_unref(in); 
      #endif  

        isHandShakeDone=0; 
        return TRUE; 
        } 

        reply = (char*)malloc(256); 
        memset(reply, 0, 1024); 
        p = reply; 

        *p = 0; 
        p++; 

        strcpy(p,"This is the server's reply!"); 
        p += strlen("This is the server's reply!"); 

        *p = 255; 
        p++; 

        ret = send(local_client_socket, reply, p-reply, 0); 
        if(ret < 0) 
        { 
       perror("\nError in sending response:"); 
        } 

       } 

       return TRUE; 

      } 



      gboolean 
      handle_socket(GIOChannel *in, GIOCondition condition, gpointer data) 
      { 
       GIOChannel *client_channel; 
       gint client_socket; 

       gint socket_fd = g_io_channel_unix_get_fd(in); 

       if(condition & G_IO_HUP) 
       { 
       printf("\nUnexpected Broken pipe error on socket_fd\n"); 
       close(socket_fd); 
       return FALSE; 
       } 

       if(isHandShakeDone==0) 
       { 

        client_socket = accept (socket_fd, NULL, NULL); 

        if (client_socket < 0) 
        { 
         g_print("ERROR CLIENT_SOCKET VALUE!!!!!!!!!!!!!!!!!!!!"); 
         return FALSE; 
        } 


        client_channel = NULL; 


        /*Program crashes on this call*/ 
        client_channel = g_io_channel_unix_new (client_socket); 
        g_io_channel_set_encoding (client_channel, NULL, NULL); 
        g_io_channel_set_buffered (client_channel, FALSE); 


        g_io_add_watch (client_channel, G_IO_IN | G_IO_HUP, (GIOFunc) read_socket, NULL); 
       } 

       return TRUE; 
      } 

      int main(int argc, char **argv) 
      { 

       GIOChannel *channel_socket; 
       gint socket_fd; 
       static GMainLoop *loop = NULL; 
       struct sockaddr_in serv_addr; 

       g_type_init(); 

       isHandShakeDone=0; 

       socket_fd = socket (AF_INET, SOCK_STREAM, 0); 
       if (socket_fd < 0) 
       { 
       g_print("Error creating socket\n"); 
       exit (1); 
       } 

       bzero((char *) &serv_addr, sizeof(serv_addr)); 

       serv_addr.sin_family = AF_INET; 
       serv_addr.sin_port = htons(49059); 
       serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 

       if (bind (socket_fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) 
       { 
       g_print("Error binding socket"); 
       exit(2); 
       } 

       listen (socket_fd, 5); 

       channel_socket = g_io_channel_unix_new (socket_fd); 
       g_io_channel_set_encoding (channel_socket, NULL, NULL); 
       g_io_channel_set_buffered (channel_socket, FALSE); 

       g_io_add_watch (channel_socket, G_IO_IN | G_IO_HUP, (GIOFunc) handle_socket, NULL); 

       g_print("GOING INTO MAINLOOP\n"); 

       loop = g_main_loop_new (NULL, FALSE); 
       g_main_loop_run (loop); 
     } 

這裏的GDB回溯:

(gdb) bt 
#0 0x002c983e in ??() from /lib/tls/i686/cmov/libc.so.6 
#1 0x002cbff6 in ??() from /lib/tls/i686/cmov/libc.so.6 
#2 0x002cdf9c in malloc() from /lib/tls/i686/cmov/libc.so.6 
#3 0x001bf244 in g_malloc() from /lib/libglib-2.0.so.0 
#4 0x001fb4ac in g_io_channel_unix_new() from /lib/libglib-2.0.so.0 
#5 0x08049b01 in handle_socket (in=0x8051f60, condition=G_IO_IN, data=0x0) at   test_server.c:498 
#6 0x001faefb in ??() from /lib/libglib-2.0.so.0 
#7 0x001b65e5 in g_main_context_dispatch() from /lib/libglib-2.0.so.0 
#8 0x001ba2d8 in ??() from /lib/libglib-2.0.so.0 
#9 0x001ba817 in g_main_loop_run() from /lib/libglib-2.0.so.0 
#10 0x08049ce4 in main (argc=1, argv=0xbffff344) at test_server.c:551 
(gdb) 
+0

什麼是551線? (#10 0x08049ce4在main(argc = 1,argv = 0xbffff344)在test_server.c:551) – CoolStraw 2011-03-15 12:38:30

+0

@CoolStraw 551行調用g_main_loop_run() – HungryTux 2011-03-15 14:04:43

+0

嗯我看不到問題。抱歉。我甚至無法編譯你的代碼。 – CoolStraw 2011-03-15 14:23:04

回答

0

@ HungryTux,你回答你自己的問題,但僅供參考,你可以

memset(reply, 0, sizeof(reply)) 

#define REPLY_SIZE 256 
reply = (char*)malloc(REPLY_SIZE);      
memset(reply, 0, REPLY_SIZE); 

通常唯一的數字是h應該出現在你的代碼中的是0,1,-1,偶爾也是2.

其他的東西都應該是一個符號!

相關問題