在 Windows 上进行 C 套接字编程时,我需要替换哪些等效的标头、函数和数据类型?

Posted

技术标签:

【中文标题】在 Windows 上进行 C 套接字编程时,我需要替换哪些等效的标头、函数和数据类型?【英文标题】:Which equivalent headers, functions, and data types do I need to replace while doing C socket programming on windows? 【发布时间】:2021-08-23 22:13:03 【问题描述】:

我最近开始了 C 套接字编程。经过几天的学习,我编写了这个程序,它监听特定 IP 和端口上的连接:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>


int main()

    printf ("The program has started\n");
    
    int sock, client_socket;
    char buffer[1024];
    char response[1024];
    struct sockaddr_in server_address, client_address;
    int i = 0;
    int optval = 1;
    socklen_t client_length;

    sock = socket(AF_INET, SOCK_STREAM, 0);

    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0)
    
        printf("Error setting TCP socket options!\n");
        return 1;
    
    else 
        printf ("TCP socket set successfully!\n");
    

    server_address.sin_family = AF_INET;
    server_address.sin_addr.s_addr = inet_addr("10.0.2.15");
    server_address.sin_port = htons(5005);

    int stat_check = bind (sock, (struct sockaddr*) &server_address, sizeof (server_address));
    if (stat_check != 0)
    
        printf ("Couldn't bind\n");
    
    else 
        printf ("binded successfully\n");
    
    
    stat_check = listen(sock, 5);
    if (!(stat_check == 0))
    
        printf ("Failed to listen!\n");
    
    else 
        printf ("Listening...\n");
    
    printf ("now the program will attempt to accept the connectionHSHA\n");
    client_length = sizeof(client_address);
    client_socket = accept (sock, (struct sockaddr*) &client_address, &client_length);
    printf ("Socket Accepted or something happened\n");
    
    if (client_socket == -1)
    
        printf ("Couldn't accept connection!\n");
    
    else 
    
        printf ("Connection Accepted!\n");
    

    while (1)
    
        jump:
        bzero(&buffer, sizeof(buffer));
        bzero(&response, sizeof(response));
        printf("* Shell#%s~$: ", inet_ntoa(client_address.sin_addr));
        fgets(buffer, sizeof(buffer), stdin);
        strtok(buffer, "\n");
        write(client_socket, buffer, sizeof(buffer));

        if (strncmp("q", buffer, 1) == 0)
        
            break;
        
        else
        
            recv(client_socket, response, sizeof(response), MSG_WAITALL);
            printf("%s", response);
        
    

这个程序在我的 Linux 系统中可以 100% 编译,但我需要它在 windows 上运行。当我使用 MinGW 编译器在我的 Windows 上编译相同的程序时,它会遇到许多缺少标题的错误。不过windows中有一些socket编程的库,比如winsock.h。但是当我用&lt;sys/socket&gt; 替换winsock.h 并删除其他Linux 库(arpa/inet.h 等)时,还有一些其他错误,如socklen_t undefined。我也收到了一些警告。

总之,如果我想在 Windows 上运行此代码,我不清楚需要替换哪些等效库、函数和数据类型。或者我可以以任何其他方式在 Windows 上运行它吗?任何建议将不胜感激。

谢谢!

【问题讨论】:

您看过winsock.h 文档吗? docs.microsoft.com/en-us/windows/win32/api/winsock 是的,Topoly。 socklen_t 似乎无处不在。我检查了 winsock.h、winsock2.h、sys/stats 和 sys/types。它们可能位于其他库之一中,Windows 不支持这些库。不过,谢谢! 嗯,是的,套接字不是 C 标准的一部分,因此 Windows 可以并且将会对相同的事物有自己的单独定义。 我不知道它不是 C 标准的一部分。那是什么? 对于套接字,什么都没有。您如何使用它们取决于平台。 【参考方案1】:

这是一个简单但完整的服务器示例,它在 Windows 下使用套接字为 TCP 提供服务。

它同时接受多个客户端,并通过一个线程为它们提供服务。 服务器接受来自每个客户端的命令行并在服务器端回显它们(通过简单的发送很容易回显给客户端)。如果命令是“退出”,则服务器关闭连接。

当然还有很多增强的空间。你明白了……

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <WinSock2.h>

#define portNo 2100
#define MAX_CLIENTS 10

struct clientData 
    int    busy;
    int    inSocket;
    HANDLE hThread;
    DWORD  threadId;
;

struct clientData cliArray[MAX_CLIENTS];
int cliCount;

DWORD WINAPI ClientThreadFunction(LPVOID lpParam)

    struct clientData* cliData = (struct clientData*)lpParam;
    printf("[%d] Client start. Socket=%d\n", cliData->inSocket, cliData->inSocket);

    char buf[1024];
    int rcvLen;
    int rcvCount = 0;
    char ch;
    while (1) 
        rcvLen = recv(cliData->inSocket, &ch, 1, 0);
        if (rcvLen <= 0)
            break;
        if (ch == '\r')
            continue;      // Ignore return character (followed by '\n')
        if (ch != '\n') 
            putchar(ch);
            buf[rcvCount++] = ch;
            buf[rcvCount] = 0; // nul terminate string
        
        else 
            printf("\n[%d] Line=\"%s\"\n", cliData->inSocket, buf);
            if (_stricmp(buf, "exit") == 0)
                break;
            rcvCount = 0;
            buf[0] = 0;
        
    

    closesocket(cliData->inSocket);

    printf("[%d] Client terminated.\n", cliData->inSocket);
    cliData->busy = 0;
    return 1;


int main(int argc, char *argv[])

    int iResult;
    WSADATA wsaData;

    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) 
        printf("WSAStartup failed: %d\n", iResult);
        return 1;
    

    int srvSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (srvSocket < 0) 
        fprintf(stderr, "Open socket failed with error %d\n", WSAGetLastError());
        return 1;
    

    struct sockaddr_in sockAddr;

    memset(&sockAddr, 0, sizeof(sockAddr));
    sockAddr.sin_family = AF_INET;
    sockAddr.sin_port = htons(portNo);
    sockAddr.sin_addr.s_addr = INADDR_ANY;

    if (bind(srvSocket, (struct sockaddr*)&sockAddr, sizeof(sockAddr))) 
        fprintf(stderr, "bind socket failed with error %d\n", WSAGetLastError());
        closesocket(srvSocket);
        WSACleanup();
        return 1;
    

    if (listen(srvSocket, 5)) 
        fprintf(stderr, "listen socket failed with error %d\n", WSAGetLastError());
        closesocket(srvSocket);
        WSACleanup();
        return 1;
    
    
    while (1) 
        int inSocket = accept(srvSocket, NULL, NULL);
        if (inSocket == INVALID_SOCKET) 
            fprintf(stderr, "accept socket failed with error %d\n", WSAGetLastError());
            closesocket(srvSocket);
            WSACleanup();
            return 1;
        
        struct clientData* cliData = cliArray;
        int i = 0;
        while ((i < MAX_CLIENTS) && cliArray[i].busy)
            i++;
        if (i >= MAX_CLIENTS) 
            // To many clients, disconnect
            closesocket(inSocket);
            printf("Too many active clients (max=%d), discarding this one\n", MAX_CLIENTS);
            continue;
        
        cliData = &cliArray[i];
        cliData->busy = 1;
        cliData->inSocket = inSocket;
        cliData->hThread = CreateThread(
            NULL,                            // default security attributes
            0,                               // use default stack size  
            ClientThreadFunction,            // thread function name
            cliData,                         // argument to thread function 
            0,                               // use default creation flags 
            &cliData->threadId);             // returns the thread identifier 
    

    closesocket(srvSocket);
    WSACleanup();
    printf("Done.\n");
    return 0;

【讨论】:

以上是关于在 Windows 上进行 C 套接字编程时,我需要替换哪些等效的标头、函数和数据类型?的主要内容,如果未能解决你的问题,请参考以下文章

Windows上erlang的开发环境

在 Mac 上找不到 lsocket 库

同时在一个套接字上进行 recv() 和 send() 是不是安全?

socket总结

用于 UDP 客户端的 Windows C 套接字编程

C 中的 Windows 套接字编程