C语言sendstring函数如何正确使用?

99ANYc3cd6
预计阅读时长 21 分钟
位置: 首页 C语言 正文

在标准的 C 语言库(如 stdio.h)中,并没有一个叫做 sendstring 的原生函数。

c语言sendstring
(图片来源网络,侵删)

sendstring 这个名字通常出现在两种场景下:

  1. 特定平台或旧系统(如 DOS)的函数:在早期的操作系统,如 MS-DOS 的 conio.h 库中,存在一个 sendstring 函数,它的作用是直接将字符串发送到控制台(屏幕),类似于 puts() 但功能更底层。
  2. 自定义函数:在网络编程中,sendstring 是一个非常常见的自定义函数(或宏)的命名,开发者为了方便,会自己写一个函数来封装 send() 系统调用,用于一次性发送一个以空字符结尾的字符串。

由于现代开发主要集中在网络编程,第二种场景(自定义函数)是目前最常见和最有意义的,我将重点讲解这个。


网络编程中的自定义 sendstring 函数

在网络编程中,我们使用 send() 函数来发送数据,但 send() 函数一次只能发送一个你指定长度的数据块(bufferlength),如果我们想发送一个完整的字符串("Hello, Server!\n"),我们需要:

  1. 获取字符串的长度(通常用 strlen())。
  2. 调用 send(),传入字符串的地址和长度。

这个过程很常用,所以程序员通常会把它封装成一个自己的函数,命名为 sendstringsend_str 等。

c语言sendstring
(图片来源网络,侵删)

为什么需要自定义 sendstring

  • 代码简洁:一行 sendstring(client_socket, "Hello"); 比写 send(client_socket, "Hello", strlen("Hello"), 0); 更简洁,可读性更高。
  • 减少错误:手动计算 strlen 并传入正确的长度是容易出错的,封装后可以避免重复代码和潜在的错误。
  • 功能扩展:你可以在自定义函数里增加额外的逻辑,
    • 在发送前加上字符串的长度(用于某些自定义协议)。
    • 增加错误处理和重试机制。
    • 在调试模式下打印出发送的内容。

如何实现一个 sendstring 函数?

下面是一个在 Linux/Unix 和 Windows (Winsock) 环境下都能使用的 sendstring 函数示例。

#include <stdio.h>
#include <string.h>
#include <sys/socket.h> // for send()
#include <unistd.h>     // for write() (备用)
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
// 在 Windows 上使用前需要链接 Ws2_32.lib
// #pragma comment(lib, "Ws2_32.lib")
#else
// Linux/Unix 的类型定义
typedef int SOCKET;
#define SOCKET_ERROR -1
#define INVALID_SOCKET -1
#define closesocket(s) close(s)
#endif
/**
 * @brief 发送一个以空字符结尾的字符串到指定的套接字。
 * 
 * @param sock 目标套接字描述符。
 * @param str 要发送的字符串指针。
 * @return int 成功返回发送的字节数,失败返回 SOCKET_ERROR。
 */
int sendstring(SOCKET sock, const char *str) {
    if (sock == INVALID_SOCKET || str == NULL) {
        return SOCKET_ERROR;
    }
    size_t len = strlen(str);
    // send() 可能不会一次性发送所有数据,需要循环发送
    // 但对于大多数简单的客户端/服务器应用,一次性发送成功是常态
    // 为了更健壮,应该实现一个循环发送的版本,下面会展示
    int bytes_sent = send(sock, str, len, 0);
    if (bytes_sent == SOCKET_ERROR) {
        perror("send failed");
        return SOCKET_ERROR;
    }
    return bytes_sent;
}
// --- 更健壮的循环发送版本 ---
int sendstring_robust(SOCKET sock, const char *str) {
    if (sock == INVALID_SOCKET || str == NULL) {
        return SOCKET_ERROR;
    }
    size_t total_len = strlen(str);
    size_t sent_len = 0;
    int bytes_sent;
    // 循环直到整个字符串发送完毕
    while (sent_len < total_len) {
        bytes_sent = send(sock, str + sent_len, total_len - sent_len, 0);
        if (bytes_sent == SOCKET_ERROR) {
            perror("send failed");
            return SOCKET_ERROR;
        }
        if (bytes_sent == 0) {
            // 对方关闭了连接
            break;
        }
        sent_len += bytes_sent;
    }
    return sent_len;
}

如何使用 sendstring 函数?

下面是一个简单的 TCP 客户端示例,展示如何使用上面的 sendstring 函数。

// 这是一个完整的客户端示例
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// ... (包含上面 sendstring 函数的代码) ...
int main() {
#ifdef _WIN32
    // Windows 初始化 Winsock
    WSADATA wsaData;
    int result = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (result != 0) {
        printf("WSAStartup failed: %d\n", result);
        return 1;
    }
#endif
    // 1. 创建套接字
    SOCKET client_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (client_socket == INVALID_SOCKET) {
        perror("socket creation failed");
#ifdef _WIN32
        WSACleanup();
#endif
        return 1;
    }
    // 2. 设置服务器地址
    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(8080); // 监听端口
    // 将 "127.0.0.1" 转换为网络地址
    inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr);
    // 3. 连接服务器
    if (connect(client_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) == SOCKET_ERROR) {
        perror("connect failed");
        closesocket(client_socket);
#ifdef _WIN32
        WSACleanup();
#endif
        return 1;
    }
    printf("Connected to server!\n");
    // 4. 使用 sendstring 发送消息
    const char *message1 = "Hello, Server! This is message 1.\n";
    const char *message2 = "How are you?\n";
    if (sendstring(client_socket, message1) == SOCKET_ERROR) {
        printf("Failed to send message 1\n");
    } else {
        printf("Sent message 1: %s", message1);
    }
    if (sendstring(client_socket, message2) == SOCKET_ERROR) {
        printf("Failed to send message 2\n");
    } else {
        printf("Sent message 2: %s", message2);
    }
    // 5. 关闭套接字
    closesocket(client_socket);
#ifdef _WIN32
    WSACleanup();
#endif
    return 0;
}

DOS/旧系统中的 sendstring

如果你是在学习非常古老的 C 语言(Turbo C/C++ for DOS),你可能会在 conio.h 头文件中找到 sendstring

  • 头文件: conio.h (Console Input/Output)
  • 函数原型: void sendtext(const char *str); (注意,有时叫 sendtext,功能相同)
  • 功能: 直接将字符串 str 输出到控制台屏幕上,光标会自动移动到字符串末尾。
  • puts() 的区别:
    • puts(str): 是标准 C 库函数,会输出字符串,然后自动换行
    • sendtext(str): 是非标准的 DOS 特有函数,输出字符串,但不会自动换行

DOS 环境下的示例

#include <conio.h> // 包含 sendtext
int main() {
    clrscr(); // 清屏,也是 conio.h 中的函数
    cprintf("This is a line from cprintf.\n"); // cprintf 不会自动换行,需要手动加 \n
    sendtext("This is a line from sendtext. "); // sendtext 也不会自动换行
    getch(); // 等待用户按一个键
    return 0;
}

特性 网络编程中的自定义 sendstring DOS 中的 sendstring (或 sendtext)
来源 程序员自定义,非标准库 旧系统库 (conio.h),非标准
用途 通过网络套接字发送字符串数据 向控制台屏幕直接输出字符串
依赖 操作系统的网络 API (send, WSASend) DOS 操作系统的控制台 I/O
平台 Windows (Winsock), Linux/Unix 等 MS-DOS, Turbo C 环境
核心逻辑 封装 send() 调用,处理字符串长度 直接调用底层 BIOS 或系统调用来写屏

在现代 C 语言编程中,当你看到 sendstring 时,99% 的情况都是指网络编程中用于发送字符串的自定义函数,理解它如何封装 send() 以及为什么要这样做,对于掌握网络编程非常重要。

c语言sendstring
(图片来源网络,侵删)
-- 展开阅读全文 --
头像
dede列表缩略图变形如何解决?
« 上一篇 03-01
织梦如何实现关键词关连文章?
下一篇 » 03-01

相关文章

取消
微信二维码
支付宝二维码

目录[+]