2014-02-13 54 views
0

这是客户端的一个朋友的代码发给我的。我对套接字编程知之甚少。它意味着有点像聊天客户端;发送文本到服务器和服务器将其发送到所有客户端。我编辑它在哪里显示执行与聊天命令上的指令彩色文本。问题是/ ls命令将被识别并且暂时不会按照预期发送到服务器,但是如果声明不会执行以外的任何其他指令。其次,使用命令或发送文本到服务器后,它不会让我使用命令或发送文本了。我可以输入,但没有任何内容通过服务器,我也没有收到典型的例如“接收到的字节12”消息;除了我使用/ dis命令从服务器断开连接之外,当然我会说“Received Bytes -1”。任何想法或建议?提前致谢。C++ Linux多线程插座问题

我还在底部提供了服务器源,因为有人认为那里存在问题。

客户端源

#include <fcntl.h> 
#include <string.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <stdio.h> 
#include <netinet/in.h> 
#include <resolv.h> 
#include <sys/socket.h> 
#include <arpa/inet.h> 
#include <unistd.h> 
#include <string> 
#include <sstream> 
#define ANSI_COLOR_RED  "\x1b[31m" 
#define ANSI_COLOR_GREEN "\x1b[32m" 
#define ANSI_COLOR_YELLOW "\x1b[33m" 
#define ANSI_COLOR_BLUE "\x1b[34m" 
#define ANSI_COLOR_MAGENTA "\x1b[35m" 
#define ANSI_COLOR_CYAN "\x1b[36m" 

#define ANSI_COLOR_BRIGHT "\x1b[1m" 
#define ANSI_COLOR_RESET "\x1b[0m" 

using namespace std; 

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

    string olr = "Global" ANSI_COLOR_RESET; 
    string help = ANSI_COLOR_CYAN "\n\n/help for a list of commands e.g help\n/ls to list online chat rooms e.g. /ls\n/j namehere to join a chat room. e.g. /j Global\n/p namehere -e codehere to private chat. e flag for encryption;\n\tnot required. e.g. /p Sunny got the dox?\n/tp to toggle receiving private messages or not e.g /tp\n/l codehere to listen for encrypted private messages. Seperate \n\tmultiple codes with a comma (,). e.g. /l 123,1234\n/st to stop listening for any encrypted messages e.g /st\n/c namehere to create a chat room. e.g. /c Journalism\n/clr to clear the screen e.g. /clr\n/dis to disconnect from the server e.g. /dis\n/con to connect to the server e.g. /con\n" ANSI_COLOR_RESET; 
    int host_port= 1604; 
    char* host_name="127.0.0.1"; 

    struct sockaddr_in my_addr; 

    char buffer[1024]; 
    int bytecount; 
    int buffer_len=0; 

    int hsock; 
    int * p_int; 
    int err; 

    hsock = socket(AF_INET, SOCK_STREAM, 0); 
    if(hsock == -1){ 
     printf("Error initializing socket %d\n",errno); 
    } 

    p_int = (int*)malloc(sizeof(int)); 
    *p_int = 1; 

    if((setsockopt(hsock, SOL_SOCKET, SO_REUSEADDR, (char*)p_int, sizeof(int)) == -1)|| 
     (setsockopt(hsock, SOL_SOCKET, SO_KEEPALIVE, (char*)p_int, sizeof(int)) == -1)){ 
     printf("Error setting options %d\n",errno); 
     free(p_int); 
    } 
    free(p_int); 

    my_addr.sin_family = AF_INET ; 
    my_addr.sin_port = htons(host_port); 

    memset(&(my_addr.sin_zero), 0, 8); 
    my_addr.sin_addr.s_addr = inet_addr(host_name); 

    if(connect(hsock, (struct sockaddr*)&my_addr, sizeof(my_addr)) == -1){ 
     if((err = errno) != EINPROGRESS){ 
      fprintf(stderr, "Error connecting socket %d\n", errno); 

     } 
    } 
    printf(ANSI_COLOR_MAGENTA "\nOnline Rooms: "); 
    printf(olr.c_str()); 
    printf(help.c_str()); 
    //Now lets do the client related stuff 
    while (true){ 
    buffer_len = 1024; 
    string pokemon; 
    pokemon = "/dis"; 
    memset(buffer, '\0', buffer_len); 
    fgets(buffer, 1024, stdin); 
    buffer[strlen(buffer)-1]='\0'; 
    stringstream ss; 
    string bufferstr; 
    ss << buffer; 
    ss >> bufferstr; 
    if (bufferstr == pokemon){ 
     close(hsock); 
    } 

    else if (bufferstr == "/help"){ 
     printf(help.c_str()); 
    } 

    else if (bufferstr == "/ls"){ 
     printf("Online Rooms: "); 
     printf(olr.c_str()); 
    } 

    else if((bytecount=send(hsock, buffer, strlen(buffer),0))== -1){ 
     fprintf(stderr, "Error sending data %d\n", errno); 
    } 

    //what happens after sent 
    //printf("Sent bytes %d\n", bytecount); 

    if((bytecount = recv(hsock, buffer, buffer_len, 0))== -1){ 
     fprintf(stderr, "Error receiving data %d\n", errno); 
    } 
    printf("Recieved bytes %d\nReceived string \"%s\"\n", bytecount, buffer); 
    } 
    //close(hsock); 

} 

服务器源

#include <fcntl.h> 
#include <string.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <stdio.h> 
#include <netinet/in.h> 
#include <resolv.h> 
#include <sys/socket.h> 
#include <arpa/inet.h> 
#include <unistd.h> 
#include <pthread.h> 

void* SocketHandler(void*); 

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

    int host_port= 1604; 

    struct sockaddr_in my_addr; 

    int hsock; 
    int * p_int ; 
    int err; 

    socklen_t addr_size = 0; 
    int* csock; 
    sockaddr_in sadr; 
    pthread_t thread_id=0; 


    hsock = socket(AF_INET, SOCK_STREAM, 0); 
    if(hsock == -1){ 
     printf("Error initializing socket %d\n", errno); 
     // goto FINISH; 
    } 

    p_int = (int*)malloc(sizeof(int)); 
    *p_int = 1; 

    if((setsockopt(hsock, SOL_SOCKET, SO_REUSEADDR, (char*)p_int, sizeof(int)) == -1)|| 
     (setsockopt(hsock, SOL_SOCKET, SO_KEEPALIVE, (char*)p_int, sizeof(int)) == -1)){ 
     printf("Error setting options %d\n", errno); 
     free(p_int); 
     // goto FINISH; 
    } 
    free(p_int); 

    my_addr.sin_family = AF_INET ; 
    my_addr.sin_port = htons(host_port); 

    memset(&(my_addr.sin_zero), 0, 8); 
    my_addr.sin_addr.s_addr = INADDR_ANY ; 

    if(bind(hsock, (sockaddr*)&my_addr, sizeof(my_addr)) == -1){ 
     fprintf(stderr,"Error binding to socket, make sure nothing else is listening on this port %d\n",errno); 
    // goto FINISH; 
    } 
    if(listen(hsock, 10) == -1){ 
     fprintf(stderr, "Error listening %d\n",errno); 
//  goto FINISH; 
    } 

    //Now lets do the server stuff 

    addr_size = sizeof(sockaddr_in); 

    while(true){ 
     printf("waiting for a connection\n"); 
     csock = (int*)malloc(sizeof(int)); 
     if((*csock = accept(hsock, (sockaddr*)&sadr, &addr_size))!= -1){ 
      printf("---------------------\nReceived connection from %s\n",inet_ntoa(sadr.sin_addr)); 
      pthread_create(&thread_id,0,&SocketHandler, (void*)csock); 
      pthread_detach(thread_id); 
     } 
     else{ 
      fprintf(stderr, "Error accepting %d\n", errno); 
     } 
    } 

FINISH: 
; 
} 

void* SocketHandler(void* lp){ 
    int *csock = (int*)lp; 

    char buffer[1024]; 
    char pokemon[3]; 
    int buffer_len = 1024; 
    int bytecount; 

    int ignore; 
    pokemon[0] = '/'; 

    if (buffer[0] == pokemon[0]){ 
     ignore = 1; 
    } else {ignore = 0;} 

    memset(buffer, 0, buffer_len); 
    if((bytecount = recv(*csock, buffer, buffer_len, 0))== -1){ 
     fprintf(stderr, "Error receiving data %d\n", errno); 
     //goto FINISH; 
    } 
    printf("Received bytes %d\nReceived string \"%s\"\n", bytecount, buffer); 
    strcat(buffer, " SERVER ECHO"); 

    if (ignore==0) { 
     if((bytecount = send(*csock, buffer, strlen(buffer), 0))== -1){ 
      fprintf(stderr, "Error sending data %d\n", errno); 
      // goto FINISH; 
     } 
    } 

    printf("Sent bytes %d\n", bytecount); 

//FINISH: 
    // free(csock); 
    //return 0; 
} 

+0

了解更多关于[poll(2)](http://man7.org/linux/man-pages/man2/poll.2.html)和[事件循环](http://en.wikipedia.org /维基/ Event_loop)。另请参阅[高级Linux编程](http://advancedlinuxprogramming.com/)。使用'g ++ -Wall -g'(或* gcc -Wall -g'编译* C *代码)编译。学习如何使用'gdb'调试器**。 –

回答

1

从你的代码我的猜测是,你正好挡住就此致电: BYTECOUNT =的recv( hsock,buffer,buffer_len,0))== -1

阻塞调用(或同步)是对函数的调用,除非它完成,否则将不会返回,因为您在说'嘿在此套接字上接收1024个字节',函数将不会返回,除非它找到1024个字节或' eom',如果那个插座是空的,你会永远等到那里。

有关的recv(...),以及如何使它非阻塞看到进一步的信息:http://pubs.opengroup.org/onlinepubs/009695399/functions/recv.html

希望这有助于我没有运行代码,只是调用看似可疑。

当你发布你的服务器代码后,出现一个大错误: SocketHandler是你的线程的入口点(它就像你的主进程的'main'),但它没有循环,你的线程退出在一次接收发送之后,然后没有人正在服务器端监听该套接字。你需要在客户端添加一个while循环到你的服务器处理程序。另外,为了将来的参考,尽量不要命名变量的“口袋妖怪”真的让人分心,让其他人更难猜测变量应该做什么。

+0

我注释了包含recv调用和其下的两个打印的声明。我现在可以使用我的命令了!输入诸如“Hi”之类的信息后,虽然信息不会再次发送到服务器。对此有何想法? – Danny

+0

这与我的答案的第二部分有关: 您的线程只执行一次'SocketHandler',然后退出(死亡,正在进行),所以每次发送消息时它都会进入套接字,但没有人正在侦听在服务器上留言(这是你的线程的工作,现在他已经死了,就像Zed宝贝一样)。你需要在一段时间内包含线程主函数(true){...}循环,确保线程rec的消息,处理它,做它需要做的事情,然后返回到侦听新消息。 – Sisnett