【问题标题】:Memset appears to freeze my program C++ and other problems I don't seeMemset 似乎冻结了我的程序 C++ 和我没有看到的其他问题
【发布时间】:2011-11-06 05:22:59
【问题描述】:

我一直在制作这个服务器,我正在使用 memset() 来清除 struct addrinfo

#include <iostream>
#include <string>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <ncurses.h>
#include <vector>

#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#define MAX_CONNECTIONS 10
#define MAX_SRSIZE 500

using namespace std;

struct bcpackage{
    string * message;
};
struct clientval{
    int fd;
};

vector<int> file_descriptors;
WINDOW * console, * input;

void * handleClient(void * arg);
void * broadcast(void * arg);

int main(int argc, char **argv)
{
    int myfd, * status;
    status = new int();
    struct addrinfo myaddrinfo, *res;

    /****************SETUP NCURSES UI******************/
    initscr();
    int y, x;
    getmaxyx(stdscr, y, x);
    console = subwin(stdscr,y - 1, x, 0, 0);
    input = subwin(stdscr,1,x,y-1,0);
    wrefresh(console);
    wprintw(input,">");
    /**************************************************/
    string port = "25544";
    wprintw(console,"port: %s\n", port.c_str());
    memset(&myaddrinfo, 0, sizeof(myaddrinfo));//Problem I think with this memset()
    myaddrinfo.ai_family = AF_UNSPEC;
    myaddrinfo.ai_socktype = SOCK_STREAM;
    myaddrinfo.ai_flags = AI_PASSIVE;
    wprintw(console,"Starting Server\n");
    int aistat = getaddrinfo(NULL, "25544", &myaddrinfo, &res);
    if( aistat == 0){
        wprintw(console,"Host Information Retrieved\n");
    }
    else{
        wprintw(console, "Error : %d\n%s\n", aistat, gai_strerror(aistat));
        getch();
        endwin();
        exit(1);
    }   //We now have our address now we create a socket
    myfd = socket(res->ai_family, res->ai_socktype,res->ai_protocol);
    if(myfd==-1){
        wprintw(console, "Socket Creation Failed\n");
        wprintw(console,"Error: %d\n%s\n", errno, strerror(errno));
        getch();
        endwin();
        exit(2);
    }
    //If all went well, we now have a socket for our server
    //we will now use the bind() function to bind our socket
    //to our program. I think that is what it does at least.
    *status = bind(myfd, res->ai_addr, res->ai_addrlen);
    //wprintw(console, "Status: %d\n", *status);
    if((*status) < 0){
        wprintw(console, "Bind failed\n");
        wprintw(console,"Error: %d\n%s\n", errno, strerror(errno));
        getch();
        endwin();
        exit(3);
    }
    else{
        wprintw(console, "Bind success\n");
    }
    //Now that we are bound, we need to listen on the socket
    *status = listen(myfd, MAX_CONNECTIONS);
    if(status>=0){
        wprintw(console, "Listening on socket\n");
    }
    else{
        wprintw(console, "Listen failed\n");
        wprintw(console,"Error: %d\n%s\n", errno, strerror(errno));
        getch();
        endwin();
        exit(4);
    }

    //Everything is setup now we send the server into a loop that will pass
    //each client to a new pthread.
    while(true){
        int *clientfd = new int();
        pthread_t * cliPID = new pthread_t();
        struct sockaddr_in * cliaddr = new struct sockaddr_in();
        socklen_t *clilen = new socklen_t();
        *clilen = sizeof(*cliaddr);
        *clientfd = accept(myfd, (struct sockaddr *)cliaddr, clilen);
        file_descriptors.push_back(*clientfd);
        pthread_create(cliPID, NULL, handleClient, clientfd);
    }
    getch();
    endwin();
    return 0;
}

void * handleClient(void * arg){//Reads and writes to the functions
    int filedesc = *((int *)arg);
    string * rcvmsg = new string();
    while(!read(filedesc, rcvmsg, MAX_SRSIZE)<=0){
        if(rcvmsg->compare("")!=0){
            wprintw(console, "Client> %s\n", rcvmsg->c_str());
            broadcast(rcvmsg);
        }
        rcvmsg->clear();
    }
    delete rcvmsg;
    pthread_exit(NULL);
}

void * broadcast(void * arg){
    string * message = (string *)arg;
    int num_fds = file_descriptors.size(); 
    for(int i = 0; i < num_fds; i++ ){
        write(file_descriptors.at(i), message, MAX_SRSIZE);
    }

}

注意,这是为linux编写的,编译时需要添加这些链接器命令,-lpthread -lncurses。 最大的问题是当我有 memset() 行时,程序甚至不会在该行之前运行任何东西。它只是坐在那里。当我注释掉那条线时,它实际上会运行。 另一个错误是,当我确实取出 memset() 行时,当我使用 gai_strerror() 时,getaddrinfo() 会给出 ai_socktype not supported 错误用 getaddrinfo() 查找错误。 请帮助我。我真的被卡住了,我看不出有什么问题。

提前致谢。

【问题讨论】:

  • 您正确使用了memset。问题出在其他地方。
  • 您肯定需要memset() 行,否则myaddrinfo 中的字段未正确初始化。当memset() 存在时,您的输出可能有问题。
  • 问题出在你的 UI 上,但我对 ncurses 不熟悉。如果我使用 cout 而不是 wprintw,该代码对我有用。
  • 您是否在wprintw(console,"Host Information Retrieved\n"); 之后的某处缺少wrefresh(console)?可能一切正常,但屏幕可能没有更新?
  • 或者更好的是直接使用你想要初始化的值:struct addrinfo myaddrinfo = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM, .ai_flags = AI_PASSIVE };

标签: c++ c sockets network-programming ncurses


【解决方案1】:

它运行得很好。发生的情况是,当程序退出时,您的 ncurses 窗口正在被销毁,并且所有数据都消失了。

return 0 之前添加一个getch(),它会神奇地工作。

【讨论】:

  • 我刚刚提交了所有代码,并且在返回 0 之前确实使用了 getch(),但它似乎仍然不起作用。
  • 其实我觉得可能是我没有像 msandiford 说的那样刷新屏幕。
猜你喜欢
  • 1970-01-01
  • 2017-05-15
  • 1970-01-01
  • 2020-04-20
  • 2017-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-01
相关资源
最近更新 更多