Windows下替代fork的方法

17

我一直在跟随 Beej网络指南,在服务器部分有一段代码,在其中调用了一个名为fork()的函数。

if (!fork()) { // this is the child process
            close(sockfd); // child doesn't need the listener
            if (send(new_fd, "Hello, world!", 13, 0) == -1)
                perror("send");
            close(new_fd);
            exit(0);

我在使用Windows电脑,但无法让这一部分正常工作。我该怎么做才能解决这个问题呢?以下是我的代码。

/* Server */
#define _WIN32_WINNT 0x501
#include <iostream>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include  <sys/types.h>


using namespace std;

const int winsockVersion = 2;
#define BACKLOG 10
#define PORT "3000"


int main(void){

    WSADATA wsadata;
    if (WSAStartup(MAKEWORD(winsockVersion,0),&wsadata) == 0){
        cout<<"-WSAStartup initialized..." << endl;

        int status;
        int sockfd, new_fd;
        const char yes = '1';
        struct addrinfo hints, *res,*loop_find;
        struct sockaddr_storage their_addr;
        socklen_t addr_size;



        memset(&hints,0,sizeof hints);
        hints.ai_family = AF_INET;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_flags = AI_PASSIVE;

        if ( (status = getaddrinfo(NULL,PORT,&hints,&res)) == 0 ){
            cout<<"-Call to get addrinfo successful!." << endl;
        }

        for (loop_find = res; loop_find!=NULL; loop_find = loop_find->ai_next){
            if ( (sockfd = socket(loop_find->ai_family,loop_find->ai_socktype,loop_find->ai_protocol) ) == -1 ){
                cout<<"-Could not create socket." << endl;
                continue;
            }else{
                cout<<"-Socket Created." << endl;
            }

            //clearing in use ports.
            if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
                cout<<"-Couldnt clear blocked port." << endl;
                perror("setsockopt");
                exit(1);
            }

            if( bind(sockfd,loop_find->ai_addr,loop_find->ai_addrlen) == -1 ){
                closesocket(sockfd);
                perror("server: bind");
                continue;
            }

            break;
        }

        if (listen(sockfd,BACKLOG) != -1){
            cout<<"-Listening for incoming connections.";
        }

        //accept loop.
        while(true){

            socklen_t addr_size = sizeof their_addr;
            new_fd = accept(sockfd,(sockaddr*)&their_addr,&addr_size);

            if ( new_fd == -1 ){
                perror("accept");
                continue;
            }

            struct sockaddr new_addr;
            int len = sizeof new_addr;
            getpeername(new_fd,&new_addr,&len);
            cout<<"-Connected to " << new_addr.sa_data << endl;

            if(!fork()){ //this is a child process
                closesocket(sockfd);
                if (send(new_fd,"hello world!!",13,0) == -1){
                    perror("send");
                    closesocket(new_fd);
                    exit(0);
                }
            }
            closesocket(new_fd);

        }
    }


    //clear stuff
    if( WSACleanup() != 0){
        cout<<"-WSACleanup unsuccessful" << endl;
    }else{
        cout<<"-WSACleanup successful" << endl;
    }


    return 0;

}

8
当你编写Windows程序时,通常需要采用另一种思维方式。我认为最好看一下Winsock教程,而不是使用你现在正在使用的这个指南。 - Prof. Falken
3个回答

28
与OJ和Vincent Robert的现有答案相反,fork()在高端版本的Windows上确实存在。它是基于UNIX的应用程序子系统(SUA)的一部分,早期称为Microsoft Windows Services for UNIX(SFU),更早称为Interix
引用http://en.wikipedia.org/wiki/Interix, SUA可用于以下系统:
  • Windows Server 2003 R2(所有版本)- 版本5.2
  • Windows Vista(旗舰版和企业版)- 版本6.0
  • Windows Server 2008(所有版本)- 版本6.0
  • Windows Server 2008 R2和Microsoft Windows 7 - 版本6.1
您只需要安装免费的SUA SDK即可使用fork()。根据您的目标系统,您需要以下之一:

You can also take a look at Interix是否实现了fork()函数?


7
所以你的意思是“只要使用正确版本的Windows并安装启用它的SDK,Fork就存在”。在我看来,它可能根本不存在。对于Windows开发者来说,“CreateProcess”是一个更简单和更好的选择(当然这是我的个人看法)。干杯! - OJ.
11
没有Windows是一个更简单、更好的选择。 - Matt Joiner
10
不幸的是,在Windows 8中,看起来SUA已被弃用,并且“将在下一个版本中完全删除”:http://brianreiter.org/2011/09/15/sua-deprecated-in-windows-8/ - RichieHindle
3
@RichieHindle,现在我们似乎将获得一个WSL替代品:https://en.wikipedia.org/wiki/Windows_Subsystem_for_Linux - Søren Boisen
1
@RichieHindle为什么不直接使用GNU/Linux呢?这样可以获得最真实的Linux命令行体验。使用WSL会有一些限制。 - tripulse
显示剩余2条评论

10

10
但实际上,在Windows下你根本不会像那样设计网络服务器。 - Len Holgate
3
fork()在Windows上并不是那么明显存在,查看我的答案。 - Piotr Dobrogost

6

fork在Windows中不存在。你需要使用一个名为CreateProcess的Windows特定API。

fork相反,CreateProcess需要EXE文件的路径。你可以通过调用带有NULL参数的GetModuleFileName来检索当前EXE的路径。


1
在Windows上确实存在fork()函数 :) 请查看我的回答。 - Piotr Dobrogost

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接