C#与C++交互开发系列(十九):跨进程通信之套接字(Sockets)

在这里插入图片描述

1、前言

套接字(Sockets)是一种强大的通信方式,可以在同一台设备或网络上的不同设备之间进行通信。C# 和 C++ 都支持套接字编程,这使得在它们之间实现跨进程通信成为可能。本文将介绍如何通过套接字实现 C# 和 C++ 程序的跨进程通信,并附带完整的示例代码,供读者参考与调试。

2、什么是套接字(Sockets)?

套接字是一种支持网络通信的接口,它允许进程在不同的计算机或同一台计算机上相互通信。套接字提供了多种协议,其中最常用的 TCP 和 UDP 协议分别适合有序可靠和快速无序的数据传输。本文重点介绍 TCP 套接字,它保证数据传输的可靠性和有序性。

3、实现步骤

  1. C++ 服务器:创建 TCP 服务器端套接字,监听特定端口,接收并处理客户端请求。
  2. C# 客户端:连接到服务器的 IP 地址和端口,向服务器发送请求并接收响应。

4、示例代码

下面的代码展示了一个 C++ 服务器和 C# 客户端之间的跨进程通信实例。C++ 服务器通过套接字接收来自 C# 客户端的消息并进行回复。

C++ 服务器代码

使用 Windows 套接字 API(Winsock)来创建一个 TCP 服务器:

#include <winsock2.h>
#include <ws2tcpip.h>
#include <iostream>
#pragma comment(lib, "ws2_32.lib")

int main() {
    WSADATA wsaData;
    SOCKET serverSocket, clientSocket;
    sockaddr_in serverAddr, clientAddr;

    // 初始化 Winsock
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        std::cerr << "WSAStartup failed. Error: " << WSAGetLastError() << std::endl;
        return 1;
    }

    // 创建服务器套接字
    serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (serverSocket == INVALID_SOCKET) {
        std::cerr << "Failed to create socket. Error: " << WSAGetLastError() << std::endl;
        WSACleanup();
        return 1;
    }

    // 配置服务器地址
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");  // 本地 IP
    serverAddr.sin_port = htons(54000);  // 使用端口 54000

    // 绑定服务器地址到套接字
    if (bind(serverSocket, (sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
        std::cerr << "Bind failed. Error: " << WSAGetLastError() << std::endl;
        closesocket(serverSocket);
        WSACleanup();
        return 1;
    }

    // 监听连接
    if (listen(serverSocket, SOMAXCONN) == SOCKET_ERROR) {
        std::cerr << "Listen failed. Error: " << WSAGetLastError() << std::endl;
        closesocket(serverSocket);
        WSACleanup();
        return 1;
    }

    std::cout << "Server is listening on port 54000..." << std::endl;

    // 接受客户端连接
    int clientSize = sizeof(clientAddr);
    clientSocket = accept(serverSocket, (sockaddr*)&clientAddr, &clientSize);
    if (clientSocket == INVALID_SOCKET) {
        std::cerr << "Accept failed. Error: " << WSAGetLastError() << std::endl;
        closesocket(serverSocket);
        WSACleanup();
        return 1;
    }

    char buffer[512];
    int bytesReceived = recv(clientSocket, buffer, 512, 0);
    if (bytesReceived > 0) {
        buffer[bytesReceived] = '\0';
        std::cout << "Received from client: " << buffer << std::endl;

        // 回复消息
        const char* reply = "Hello from C++ Server";
        send(clientSocket, reply, strlen(reply), 0);
    }

    // 关闭套接字
    closesocket(clientSocket);
    closesocket(serverSocket);
    WSACleanup();
    return 0;
}

代码解析

  • WSAStartup:初始化 Winsock 库。
  • socket:创建 TCP 套接字。
  • bind:将服务器 IP 地址和端口绑定到套接字。
  • listen:监听客户端连接。
  • accept:接受客户端的连接请求。
  • recvsend:分别用于接收和发送数据。

C# 客户端代码

在 C# 中使用 TcpClient 类连接到 C++ 服务器:

using System;
using System.IO;
using System.Net.Sockets;
using System.Text;

class Program {
    static void Main() {
        try {
            // 创建客户端并连接到服务器
            using (TcpClient client = new TcpClient("127.0.0.1", 54000)) {
                Console.WriteLine("Connected to server.");

                // 发送消息到服务器
                string message = "Hello from C# Client";
                byte[] data = Encoding.UTF8.GetBytes(message);
                NetworkStream stream = client.GetStream();
                stream.Write(data, 0, data.Length);

                // 接收服务器回复
                data = new byte[512];
                int bytes = stream.Read(data, 0, data.Length);
                string response = Encoding.UTF8.GetString(data, 0, bytes);
                Console.WriteLine("Received from server: " + response);
            }
        } catch (Exception e) {
            Console.WriteLine("Error: " + e.Message);
        }
    }
}

代码解析

  • TcpClient:创建 TCP 客户端并连接到服务器。
  • NetworkStream:从客户端发送和接收数据。
  • Encoding.UTF8.GetBytes:将字符串转换为字节数组,以便发送。
  • stream.Read:读取服务器返回的数据。

5、运行步骤

  1. 编译并运行 C++ 服务器,等待客户端连接。
  2. 运行 C# 客户端,连接到服务器,发送并接收消息。

运行结果:
在这里插入图片描述

  • 服务器输出:Received from client: Hello from C# Client
  • 客户端输出:Received from server: Hello from C++ Server

6、注意事项

  1. 端口号:确保服务器和客户端使用相同的端口号。
  2. 编码格式:通信时要使用相同的字符编码,以确保数据的正确解析。
  3. 异常处理:在生产环境中,建议加入更多的异常处理,确保套接字连接失败时能够正确地释放资源。

7、应用场景

  • 分布式系统:如微服务架构,跨网络或不同设备的模块之间的通信。
  • 实时数据传输:适用于对数据实时性要求较高的应用,如即时消息系统或在线游戏。

8、优缺点

  • 优点

    • 支持跨网络的进程间通信。
    • 适合大量数据和复杂数据结构的传输。
    • 可以建立长时间的连接,适合实时通信场景。
  • 缺点

    • 需要手动管理连接状态和异常。
    • 实现较复杂,需要处理数据分段和重组。

9、总结

本文介绍了如何在 C# 和 C++ 程序之间通过 TCP 套接字进行通信。通过套接字,跨进程的数据传输不仅限于同一设备,还可以扩展到网络中的其他设备,为分布式系统的构建提供了可能。
在下一篇文章中,我们将探讨 共享内存(Shared Memory) 的实现方法,它在性能方面更加优越,适用于大数据量、低延迟的通信需求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/911337.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python | Leetcode Python题解之第538题把二叉搜索树转换为累加树

题目&#xff1a; 题解&#xff1a; class Solution:def convertBST(self, root: TreeNode) -> TreeNode:def getSuccessor(node: TreeNode) -> TreeNode:succ node.rightwhile succ.left and succ.left ! node:succ succ.leftreturn succtotal 0node rootwhile nod…

几个docker可用的镜像源

几个docker可用的镜像源 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; sudo rm -rf /etc/docker/daemon.json sudo mkdir -p /etc/dockersudo tee /etc/docker/daemon.json <<-EOF {"registry-mirrors": ["https://d…

java ssm 校园快递物流平台 校园快递管理系统 物流管理 源码 jsp

一、项目简介 本项目是一套基于SSM的校园快递物流平台&#xff0c;主要针对计算机相关专业的和需要项目实战练习的Java学习者。 包含&#xff1a;项目源码、数据库脚本、软件工具等。 项目都经过严格调试&#xff0c;确保可以运行&#xff01; 二、技术实现 ​后端技术&#x…

Sentinel通过限流对微服务进行保护

目录 雪崩问题 解决雪崩问题的方法&#xff1a; 我们使用sentinel组件实现微服务的保护 一&#xff1a;下载sentinel 二.启动sentinel 三.访问&#xff1a;localhost:8080 默认的账号和密码都是sentinel 微服务整合sentinel 一.导入sentinel依赖 二.在application.yml配…

【Linux】冯诺依曼体系、再谈操作系统

目录 一、冯诺依曼体系结构&#xff1a; 1、产生&#xff1a; 2、介绍&#xff1a; 二、再谈操作系统&#xff1a; 1、为什么要管理软硬件资源&#xff1a; 2、操作系统如何进行管理&#xff1a; 3、库函数&#xff1a; 4、学习操作系统的意义&#xff1a; 一、冯诺依曼…

斗破QT编程入门系列之二:GUI应用程序设计基础:UI文件(四星斗师)

斗破Qt目录&#xff1a; 斗破Qt编程入门系列之前言&#xff1a;认识Qt&#xff1a;Qt的获取与安装&#xff08;四星斗师&#xff09; 斗破QT编程入门系列之一&#xff1a;认识Qt&#xff1a;初步使用&#xff08;四星斗师&#xff09; 斗破QT编程入门系列之二&#xff1a;认识…

ffmpeg命令

1. 修改视频的数据速率 ffmpeg.exe -i video.mp4 -r 30 -c:v libx264 -b:v 1500k output.mp42. mp4与h264互相转换 ffmpeg.exe -i a.mp4 -vcodec h264 output.h264 ffmpeg.exe -i output.h264 -vcodec mpeg4 output.mp4

前端三件套-css

一、元素选择器 元素选择器&#xff1a;利用标签名称。p,h1-h6...... 行内样式&#xff08;内联样式&#xff09;&#xff1a;例如<p style"color:red;font-size:50px"> id选择器&#xff1a;针对某一个特定的标签来使用。以#定义。 class&#xff08;类&a…

c++设计模式demo

模式设计原则 依赖倒置原则 ⾼层模块不应该依赖低层模块&#xff0c;⼆者都应该依赖抽象 &#xff1b; 抽象不应该依赖具体实现&#xff0c;具体实现应该依赖于抽象&#xff1b; ⾃动驾驶系统公司是⾼层&#xff0c;汽⻋⽣产⼚商为低层&#xff0c;它们不应该互相依赖&#x…

操作系统学习笔记-4.1文件管理

文章目录 文件的逻辑结构1. 顺序结构特点应用场景示例 2. 索引结构特点应用场景示例 3. 链接结构特点应用场景示例 总结 文件目录文件的物理结构1. 连续分配&#xff08;Contiguous Allocation&#xff09;2. 链接分配&#xff08;Linked Allocation&#xff09;隐式链接 3. 索…

ES文档:文档操作_doc(7.9.2)

用心记录技术&#xff0c;走心分享&#xff0c;始于后端&#xff0c;不止于后端&#xff0c;励志成为一名优秀的全栈架构师&#xff0c;真正的实现码中致富。 ElasticSearch文档的操作&#xff1b; 添加文档 新建一个索引 goboy-blog&#xff0c;如果添加文档索引不存在则会创…

深入解析 WinForms MVVM 模式中的事件驱动与数据驱动

前言 在传统的 WinForms 开发中&#xff0c;事件驱动模型&#xff08;Event-Driven Model&#xff09;是核心&#xff0c;它通过控件的事件&#xff08;如点击按钮、改变文本等&#xff09;触发业务逻辑。然而&#xff0c;MVVM 模式引入了数据驱动&#xff08;Data-Driven&…

Python中的 if __name__ == ‘__main__

在Python中&#xff0c;if __name__ __main__: 这行代码有一个特定的用途和含义。为了理解它&#xff0c;我们需要先了解Python中的__name__变量以及Python脚本是如何执行的。 __name__变量 每个Python模块&#xff08;python文件&#xff09;都有一个内置的属性__name__。当…

【系统面试篇】进程与线程类(2)(笔记)——进程调度、中断、异常、用户态、核心态

目录 一、相关面试题 1. 进程的调度算法有哪些&#xff1f; 调度原则 &#xff08;1&#xff09;先来先服务调度算法 &#xff08;2&#xff09;最短作业优先调度算法 &#xff08;3&#xff09;高响应比优先调度算法 &#xff08;4&#xff09;时间片轮转调度算法 &am…

大数据工具 flume 的安装配置与使用 (详细版)

参考网址&#xff1a;Flume 1.9用户手册中文版 — 可能是目前翻译最完整的版本了 1&#xff0c;上传安装包 安装包链接&#xff1a;文件下载-奶牛快传 Download &#xff5c;CowTransfer 口令&#xff1a;x8bhcg 1&#xff0c;切换盘符到安装目录 cd /opt/moudles 解压文件…

使用uni-app框架开发各种web前端程序

使用uni-app框架开发各种web前端程序是目前非常流程的开发方式&#xff0c;比如开发APP、小程序、H5等等&#xff0c;是一个使用 vue 开发所有前端应用的框架&#xff0c;开发者编写一套代码&#xff0c;可发布到ios&#xff0c;安卓、H5、以及各种小程序&#xff08;微信、支付…

鸿蒙ArkTS中的布局容器组件(Column、Row、Flex、 Stack、Grid)

在鸿蒙ArkTS中&#xff0c;布局容器组件有很多&#xff0c;常见的有&#xff1a;   ⑴ Column&#xff1a;&#xff08;垂直布局容器&#xff09;&#xff1a;用于将子组件垂直排列。   ⑵ Row&#xff1a;&#xff08;水平布局容器&#xff09;&#xff1a;用于将子组件水…

简单介绍一下mvvm mvc mvp以及区别、历史

MVC&#xff08;Model - View - Controller&#xff09; 因MVC架构的灵活性&#xff0c;架构图形式很多&#xff0c;仅供参考 历史&#xff1a; MVC 是最早出现的软件架构模式之一&#xff0c;其历史可以追溯到 20 世纪 70 年代&#xff0c;最初被用于 Smalltalk - 80 环境。…

黑马程序员linux学习【持续更新】

Linux基础 一、Linux简介 1.分类 不同领域的主流操作系统&#xff0c;主要分为下 几类&#xff1a;桌面操作系统、服务器操作系统、移动设备操作系统、嵌入式操作系统。 桌面操作系统 操作系统特点Windows用户数量最多MacOS操作体验好&#xff0c;办公人士首选Linux用户数…

Vert.x,应用监控 - 全链路跟踪,基于Zipkin

关于Zipkin Zipkin是一款开源的分布式实时数据追踪系统(Distributed Tracking System)&#xff0c;能够收集服务间调用的时序数据&#xff0c;提供调用链路的追踪。Zipkin每一个调用链路通过一个trace id来串联起来&#xff0c;通过trace id&#xff0c;就能够直接定位到这次调…