具有fd传递的多进程TCP服务器

时间:2016-02-22 09:08:41

标签: c++ sockets tcp network-programming

我学习网络编程,我有疑问,请帮帮我! 让我来描述我的问题,在基础epoll上我写了tcp服务器。所以它很棒,但是我想做这个服务器多进程,为了实现它我决定使用fd-passing between main process and workers 所以我编写了代码,但似乎它工作不正确。

#define MAX_EVENTS 32

int set_nonblock(int fd){
int flags;
#if defined(O_NONBLOCK)
if (-1 == (flags = fcntl(fd,F_GETFL, 0)))
    flags = 0;
return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
#else 
flags = 1;
return ioctl(fd, FIONBIO, &flags); 
#endif
}

它的功能需要做套接字非阻塞,接下来 它是工人流程的代码

 void child(int sock)
{
int fd;
char    buf[16];
ssize_t size;

sleep(1);
for (;;) {
    size = sock_fd_read(sock, buf, sizeof(buf), &fd);
    if (size <= 0)
        break;
    if (fd != -1) {
    static char Buffer[1024];
    std::string answer;

    int RecvResult = recv(fd,
            Buffer, 1024, MSG_NOSIGNAL);
    if (RecvResult == 0 && errno != EAGAIN){
        shutdown(fd,SHUT_RDWR);
        close(fd);
    }else if (RecvResult >0){
        for (int i = 0; i < RecvResult; ++i){
            answer += Buffer[i];
        }
        int pid = getpid();

   std::stringstream ss; 
   ss << pid; 



        answer += ss.str() + "\n";
        send(fd, answer.c_str(), answer.size(),MSG_NOSIGNAL);
    }
  }
}
printf("child processes is end\n");
}

那么,主要进程的下一个代码类

struct Descriptors{
int sv[2]; 
};

  class Parent{
  public:
static Parent& getInstance(){
    static Parent instance;
    return instance;
}
Parent(Parent const&)         = delete;
    void operator=(Parent const&)  = delete;
void addFd(int fd){
    m_fd.push_back(fd);
};
void run() {
    int MasterSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
std::set<int> SlaveSockets;

struct sockaddr_in SockAddr;
SockAddr.sin_family = AF_INET;
SockAddr.sin_port = htons(12347);
SockAddr.sin_addr.s_addr = htonl(INADDR_ANY);

bind(MasterSocket, (struct sockaddr *)(&SockAddr), sizeof(SockAddr));

set_nonblock(MasterSocket);
listen(MasterSocket, SOMAXCONN);
int Epoll = epoll_create1(0);
struct epoll_event Event;
Event.data.fd = MasterSocket;
Event.events = EPOLLIN;

epoll_ctl(Epoll, EPOLL_CTL_ADD, MasterSocket, &Event);
size_t index = 0;
while(true){
    struct epoll_event Events[MAX_EVENTS];
    int N = epoll_wait(Epoll, Events, MAX_EVENTS, -1);
    for (size_t i =0; i < N; ++i){
        if (Events[i].data.fd == MasterSocket) {
            int SlaveSocket = accept(MasterSocket, 0, 0);
            set_nonblock(SlaveSocket);
            struct epoll_event Event;
            Event.data.fd = SlaveSocket;
            Event.events = EPOLLIN;

            epoll_ctl(Epoll, EPOLL_CTL_ADD, SlaveSocket, &Event);

        }else {
            char * arg = "1";
             ssize_t size = sock_fd_write(m_fd[index], arg, 1,Events[i].data.fd);
            index = (1+index) % m_fd.size();

        }       
    }
}

}
private:
Parent(){
    m_numCpu = sysconf(_SC_NPROCESSORS_ONLN);
}
int m_numCpu;
std::vector<int> m_fd;
};

void parent(int sock){
    Parent::getInstance().addFd(sock);


}

和我的主要功能:

int main(int argc, char **argv){
int numCpu = sysconf(_SC_NPROCESSORS_ONLN); 
std::cout << "parent pid = " << getpid() << std::endl;
std::vector<Descriptors> desc;
desc.resize(numCpu);

bool isParent = true;
for (int i  = 0; i < numCpu && isParent; ++i){
    std::cout << "pid my is = " << getpid() <<std::endl;
    int sv[2];
      if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) < 0) {
               perror("socketpair");
              exit(1);
        }       
    pid_t forkId = fork();
    switch (forkId){
        case 0:{
            isParent = false;
            close(sv[0]);
                child(sv[1]);
                break;
        }   
          case -1:
                   perror("fork");
                    exit(1);
            default:
                close(sv[1]);
                parent(sv[0]);
                break;
        }   
}
  if (isParent){
    std::cout << "pid parent after create = " << getpid()
            << " parent od parent = " <<getppid() << std::endl;
    Parent::getInstance().run();
    int status;
    waitpid(-1, &status, 0);

}

所以第一个错误是当一个客户端断开连接时,我的服务器变得很奇怪 请问你能帮帮我吗!感谢您的任何建议和任何有用的链接!!!

0 个答案:

没有答案