You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Windows下客户端/服务器Socket程序运行异常:启动后立即退出

问题:Windows下Socket传输程序运行后自动关闭

我使用以下命令编译了客户端和服务器代码:

  • 服务器:gcc server.c -o server.exe -lws2_32
  • 客户端:gcc client.c -o client.exe -lws2_32

代码编译成功生成对应.exe文件,但运行server.exe和client.exe时,程序打开后会突然自动关闭,无法查看完整运行日志。

原因分析

  • Winsock库未初始化与清理:Windows平台下使用Winsock API必须先调用WSAStartup完成库初始化,结束时调用WSACleanup,否则socket()等核心函数会调用失败,直接触发exit(1)导致程序闪退。
  • 端口未转换为网络字节序:TCP/IP协议要求端口号使用网络字节序(大端),代码中直接赋值端口号给sin_port,未用htons()转换,会导致绑定或连接失败。
  • 程序执行完毕后无暂停:控制台程序执行完main()函数后会立即关闭窗口,无法查看输出,需要添加暂停逻辑。
  • 代码逻辑缺陷:
    • 服务器端write_file函数中,break后的return永远不会执行;客户端发送完文件后未主动关闭写入端socket,导致服务器recv()一直阻塞,直到连接异常断开。
    • 客户端send_file函数用sizeof(data)发送数据,会把缓冲区空字符一并发送,应使用strlen(data)获取实际读取的文件内容长度。

修复后的代码

服务器端(server.c)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#define SIZE 1024

void write_file(int sockfd){
    int n;
    FILE *fp;
    char *filename = "file2.txt";
    char buffer[SIZE];
    fp = fopen(filename, "w");
    if(fp==NULL){
        perror("[-]Error in creating file.");
        exit(1);
    }
    while(1){
        n = recv(sockfd, buffer, SIZE, 0);
        if(n<=0){
            break;
        }
        fprintf(fp, "%s", buffer);
        memset(buffer, 0, SIZE);
    }
    fclose(fp);
    printf("[+]Data written to the text file successfully\n");
}

int main (){
    WSADATA wsaData;
    // 初始化Winsock库
    if(WSAStartup(MAKEWORD(2,2), &wsaData) != 0){
        perror("[-]WSAStartup failed");
        exit(1);
    }

    char *ip = "127.0.0.1";
    int port = 8080;
    int e;
    int sockfd, new_sock;
    struct sockaddr_in server_addr, new_addr;
    int addr_size;
    char buffer[SIZE];

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd<0){
        perror("[-]Error in socket");
        WSACleanup();
        exit(1);
    }
    printf("[+]Server socket created.\n");

    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port); // 转换为网络字节序
    server_addr.sin_addr.s_addr = inet_addr(ip);

    e = bind(sockfd,(struct sockaddr*)&server_addr, sizeof(server_addr));
    if(e<0){
        perror("[-]Error in Binding");
        closesocket(sockfd);
        WSACleanup();
        exit(1);
    }
    printf("[+]Binding Successful.\n");

    e = listen(sockfd, 10);
    if(e==0){
        printf("[+]Listening...\n");
    }
    else{
        perror("[-]Error in Listening");
        closesocket(sockfd);
        WSACleanup();
        exit(1);
    }

    addr_size = sizeof(new_addr);
    new_sock = accept(sockfd,(struct sockaddr*)&new_addr, &addr_size);
    if(new_sock < 0){
        perror("[-]Error in accept");
        closesocket(sockfd);
        WSACleanup();
        exit(1);
    }
    printf("[+]Client connected.\n");

    write_file(new_sock);

    closesocket(new_sock);
    closesocket(sockfd);
    WSACleanup();

    // 添加暂停,防止窗口立即关闭
    printf("\nPress Enter to exit...");
    getchar();
    return 0;
}

客户端(client.c)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#define SIZE 1024

void send_file(FILE *fp, int sockfd){
    char data[SIZE] = {0};
    while(fgets(data, SIZE, fp)!=NULL){
        // 发送实际读取的内容长度,而非整个缓冲区大小
        if(send(sockfd, data, strlen(data), 0)== -1){
            perror("[-] Error in sending data");
            exit(1);
        }
        memset(data, 0, SIZE);
    }
    // 关闭socket的写入端,通知服务器文件发送完成
    shutdown(sockfd, SD_SEND);
}

int main(){
    WSADATA wsaData;
    if(WSAStartup(MAKEWORD(2,2), &wsaData) != 0){
        perror("[-]WSAStartup failed");
        exit(1);
    }

    char *ip = "127.0.0.1";
    int port = 8080;
    int e;
    int sockfd;
    struct sockaddr_in server_addr;
    FILE *fp;
    char *filename = "file.txt";

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd<0){
        perror("[-]Error in socket");
        WSACleanup();
        exit(1);
    }
    printf("[+]Client socket created.\n");

    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port); // 转换为网络字节序
    server_addr.sin_addr.s_addr = inet_addr(ip);

    e = connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
    if(e == -1){
        perror("[-]Error in Connecting");
        closesocket(sockfd);
        WSACleanup();
        exit(1);
    }
    printf("[+]Connected to server.\n");

    fp = fopen(filename, "r");
    if(fp == NULL){
        perror("[-]Error in reading file.");
        closesocket(sockfd);
        WSACleanup();
        exit(1);
    }

    send_file(fp,sockfd);
    fclose(fp);
    printf("[+] File data sent successfully.\n");

    closesocket(sockfd);
    WSACleanup();

    // 添加暂停,防止窗口立即关闭
    printf("\nPress Enter to exit...");
    getchar();
    return 0;
}

编译与运行说明

保持原编译命令不变:

  • 服务器:gcc server.c -o server.exe -lws2_32
  • 客户端:gcc client.c -o client.exe -lws2_32

运行时先启动server.exe,待显示"Listening..."后再启动client.exe,程序执行完毕后会等待按下Enter才关闭窗口,可查看完整运行日志。

内容的提问来源于stack exchange,提问作者Chandima Maduwantha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 10:40:58