嵌入式上位机开发入门(四):TCP 编程 —— Client 端实现

嵌入式上位机开发入门(四):TCP 编程 ------ Client 端

目录

一、前言

大家好,这里是 Hello_Embed 。前一篇我们实现了 TCP Server 程序,本篇来创建 TCP 客户端通信。Client 端的流程会比 Server 端略微简单,详细流程可参见同系列笔记第二篇。


二、Client 端通信流程

按照 TCP 通信流程,Client 端只需四个步骤:

  1. open socket(socket)
  2. connect to server(connect)
  3. send and receive data(send/recv)
  4. close connection(close)

与 Server 端相比,Client 不需要 bind 绑定本地地址,也不需要 listen 监听,因此流程更简洁。


三、完整代码实现

cpp 复制代码
#define _WIN32_WINNT 0x0600
#include<iostream>
#include<WinSock2.h>
#include<ws2tcpip.h>
#pragma comment(lib, "Ws2_32.lib")
#define SERVER_PORT 8888

int main(int argc, char **argv)
{
    WSADATA wsa;
    int iSocketClient;
    struct sockaddr_in tSocketServerAddr;
    if(argc != 2) {
        printf("Usage: %s <server_ip>\r\n", argv[0]);
        return -1;
    }
    if(WSAStartup(MAKEWORD(2,2), &wsa) != 0) return -1;
    iSocketClient = (int)socket(AF_INET, SOCK_STREAM, 0);
    tSocketServerAddr.sin_family = AF_INET;
    tSocketServerAddr.sin_port = htons(SERVER_PORT);
    int rc = inet_pton(tSocketServerAddr.sin_family, argv[1], &tSocketServerAddr.sin_addr);
    if(rc <= 0) {
        printf("invalid server_ip\n");
        return -1;
    }
    memset(tSocketServerAddr.sin_zero, 0, 8);
    int iRet = connect(iSocketClient, (struct sockaddr*)&tSocketServerAddr, sizeof(tSocketServerAddr));
    if(-1 == iRet) {
        printf("connect error\n");
        return -1;
    }
    while(1) {
        char ucSendBuf[1024];
        if(fgets((char*)ucSendBuf, sizeof(ucSendBuf), stdin)) {
            int iSendLen = send(iSocketClient, (char*)ucSendBuf, (int)strlen((char*)ucSendBuf), 0);
            if(iSendLen <= 0) {
                printf("send error\n");
                closesocket(iSocketClient);
                return -1;
            }
        }
    }
    return 0;
}

四、代码解析

1. 参数检查

cpp 复制代码
if(argc != 2)
{
    printf("Usage: %s <server_ip>\r\n", argv[0]);
    return -1;
}

argcargv[] 用于接收命令行传入的参数。argc 至少为 2(程序名 + 服务器 IP),否则打印用法提示并退出。

2. 创建 socket 并配置服务器地址

cpp 复制代码
iSocketClient = (int)socket(AF_INET, SOCK_STREAM, 0);
tSocketServerAddr.sin_family = AF_INET;
tSocketServerAddr.sin_port = htons(SERVER_PORT);
int rc = inet_pton(tSocketServerAddr.sin_family, argv[1], &tSocketServerAddr.sin_addr);
  • socket:创建 TCP 套接字
  • htons(SERVER_PORT):将端口号转换为网络字节序
  • inet_pton:将点分十进制 IP 地址(如 127.0.0.1)转换为网络字节序存储到结构体中

inet_ptoninet_addr 更现代,能处理更多边界情况,推荐使用。

3. 连接服务器

cpp 复制代码
int iRet = connect(iSocketClient, (struct sockaddr*)&tSocketServerAddr, sizeof(tSocketServerAddr));
if(-1 == iRet)
{
    printf("connect error\n");
    return -1;
}

connect 向服务器发起连接请求。如果服务器未启动或地址错误,会返回 -1。

4. 发送数据

cpp 复制代码
while(1)
{
    char ucSendBuf[1024];
    if(fgets((char*)ucSendBuf, sizeof(ucSendBuf), stdin))
    {
        int iSendLen = send(iSocketClient, (char*)ucSendBuf, (int)strlen((char*)ucSendBuf), 0);
        if(iSendLen <= 0)
        {
            printf("send error\n");
            closesocket(iSocketClient);
            return -1;
        }
    }
}

从控制台读取数据,使用 send 函数发送。如果发送失败,说明连接已断开,需关闭套接字并退出。


五、运行与测试

程序要求传入服务器 IP 作为参数:

bash 复制代码
tcp_client_test.exe <server_ip>

方法一:使用 SSCOM 作为服务器

  1. SSCOM 设置 TCP Server,端口 8888,点击"侦听"
  2. 在当前文件目录打开 PowerShell
  3. 输入 .\tcp_client_test.exe 127.0.0.1
  4. 可观察到 SSCOM 下方显示"已连接"
  5. 在 PowerShell 发送数据,SSCOM 可正常接收

方法二:Server 与 Client 程序互连

运行 tcp_client_test.exe,然后运行前一篇的 tcp_server_test.exe,两者可实现双向通信。发送数据进行测试:

左半图为 tcp_server_test 程序,右半图为 tcp_client_test 程序。


六、总结

  • connect:Client 主动向服务器发起连接
  • send:发送数据到服务器
  • recv:接收服务器返回的数据
  • closesocket:关闭连接

Client 端的核心是"主动连接 → 发送数据",流程简洁,只需四步即可完成通信。


七、结尾

本篇我们实现了 TCP 客户端程序,下一篇将记录 UDP 服务端的编写,打通 TCP 与 UDP 两种通信方式的完整知识体系。

Hello_Embed 继续带你从原理到实践,掌握嵌入式上位机开发的核心技能,敬请关注~

相关推荐
Freak嵌入式4 小时前
一文搞懂树莓派 Pico 任务调度器:基于定时器的 MicroPython 多任务实现
嵌入式
草莓熊Lotso5 小时前
【Redis 初阶】Set 类型深度解析:去重集合的运算能力与实战场景
linux·网络·数据库·windows·redis·tcp/ip·缓存
XR1234567886 小时前
汽车制造园区网络怎么建?柔性产线与 AGV 的选型逻辑
网络·汽车·制造
IT大白鼠15 小时前
MSF二次开发与自定义模块编写
网络·安全·web安全·msf
Julien200415 小时前
调查和解决 SELinux 问题
linux·运维·服务器·网络·学习方法
kekekzt17 小时前
TCP协议的粘包问题介绍,IP分片,MTU,MSS,滑动窗口的概念及之间的关系
网络·网络协议·tcp/ip
sakiko_18 小时前
Swift学习笔记42-SwiftUI的属性包装器(讲解+面试)
笔记·学习·ios·swiftui·swift
自小吃多19 小时前
器件移动、旋转、镜像、对齐、等间距操作笔记
笔记·嵌入式硬件
mooooooooooye19 小时前
2026 年跨平台 SSH 客户端怎么选?Xterminal、Termius、MobaXterm 谁更合适
服务器·网络·ssh
Blockchina19 小时前
Codex 实战:从一句需求到可验收的 Linux 主机巡检脚本
运维·服务器·网络