Unity C#作为客户端与C++服务器 传递结构体进行Socket通讯
最近接触到C#和C++进行SOCKET通讯的问题。
讲述一下我的情况:
和我合作的是一个只懂C++的程序员 , 而我是一个经常使用C# 对C++知之甚少的人, 没办法 半路出家。
C++的服务器是他写的 C#的客户端是我写的。 说实话,这个问题困扰了我长达2周之久。 期间我有一种我是中国人而那个人却是个美国人的感觉。
下面贴一下思路和代码
C++这边我不是特别会写,在网上找了个简单的代码稍微改了改建立Socket服务器
[code]#include <thread> #include "winsock2.h" #include <iostream> WORD sockVersion = MAKEWORD(2, 2); WSADATA wsaData; if (WSAStartup(sockVersion, &wsaData) != 0) { return 0; } //创建套接字 slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (slisten == INVALID_SOCKET) { printf("socket error !"); return 0; } //绑定IP和端口 sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = htons(8888); sin.sin_addr.S_un.S_addr = INADDR_ANY; if (_WINSOCK2API_::bind(slisten, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR) { printf("bind error !"); } //开始监听 if (listen(slisten, 5) == SOCKET_ERROR) { printf("listen error !"); return 0; } //循环接收数据 thread task01(SendData);
SendData函数的方法可以自己写 , 这里开了个线程不听的发送。 方法体主要写自己要发送的内容
[code]//发送数据 void SendData() { while (true) { printf("等待连接...\n"); sClient = accept(slisten, (SOCKADDR *)&remoteAddr, &nAddrlen); if (sClient == INVALID_SOCKET) { printf("accept error !"); continue; } printf("接受到一个连接"); //发送数据 send(sClient, (char*)(&cvData), sizeof(OpenCvData), 0); } }
到这里就需要说一下 C++和C# 之间的数据格式需要在网上查一下 我这里发送的是一段Double类型的结构体。如下:
[code]struct OpenCvData { double pos[32]; double LinePos[4]; }cvData;
好了 C++部分的服务器已经完成了。
现在是C#部分的客户端接收了,这里不累述。直接贴代码。 讲一下流程
1.建立SOCKET客户端
2.创建和C++对应类型的结构体 并序列化和规定好长度
3.解析接收到的字节,转换成自己需要的结构体
第一步的代码如下,初始化的时候就把SOCKET建立好 并开启线程接收。
[code]public ClientSocket(RobotT handler) { ip = IPAddress.Parse("127.0.0.1"); port = 8888; reciveMsg = handler; clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); clientSocket.Connect(ip, port); Thread reciveMessageFromServer = new Thread(ReciveMessageFromServer); reciveMessageFromServer.Start(); }
第二步代码如下,这里要重点讲一下,因为我写结构体的时候并没有初始化 ,所以在新建一个对象以后要对他进行初始化
[code] private void ReciveMessageFromServer() { while (true) { if (clientSocket == null) { Debug.Log("客户端的套接字没了"); continue; } Debug.Log("服务器向客户端发送消息成功"); int bufferCount = clientSocket.Receive(buffer); //阻塞型接收 // string msg = Encoding.UTF8.GetString(buffer, 0, bufferCount); try { DS = new DataStruct(); DS.Pos = new double[32]; DS.LinePos = new double[4]; DS = (DataStruct)BytesToStruct(buffer, DS.GetType()); for (int i = 0; i < DS.Pos.Length; i++) { Debug.Log(DS.Pos[i]); } for (int i = 0; i < DS.LinePos.Length; i++) { Debug.Log(DS.LinePos[i]); } } catch (Exception) { Debug.Log("数据异常"); continue; } } }
第三步其实应该是第二步 ,但是为了好给大家呈现解析的代码 就放在这里写了。
下面是和C++对应的结构体,这里需要说明一下
第一行是序列化这个结构体
第二行是结构体的大小
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] 这个是设置序列化的数据的长度
[code][Serializable] [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct DataStruct { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public double[] Pos; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public double[] LinePos; }
以下是字节转换成结构体的代码,直接复制粘贴就好了
[code] public object BytesToStruct(byte[] bytes, Type type) { int size = Marshal.SizeOf(type); IntPtr structPtr = Marshal.AllocHGlobal(size); Marshal.Copy(bytes, 0, structPtr, size); object obj = Marshal.PtrToStructure(structPtr, type); Marshal.FreeHGlobal(structPtr); return obj; }
全部代码就是这些了,写的比较急可能不是特别详细 。有不明白的可以问我
- 服务器java客户端C#的Socket通讯遇到的坑
- 简单用C#编写socket作为客户端与Linux下C++编写服务器端通信(未完善)
- C#调用c++的dll,结构体数组作为引用参数的传递方式
- unity客户端与c++服务器之间的简单通讯_1
- Android客户端,服务器,如何进行socket通讯的?
- C# Sockets实现服务器与多个客户端进行通讯
- C#(服务器)与Java(客户端)通过Socket传递对象
- Linux C利用Socket套接字进行服务器与多个客户端进行通讯
- C#(服务器)与Java(客户端)通过Socket传递对象(序列化 json)
- 【笔记】unity中socket的用法(二、服务器与客户端之间简单的数据传递)
- Linux C利用Socket套接字进行服务器与多个客户端进行通讯
- 利用C#进行socket编程(模拟服务器和客户端通信)
- 安卓客户端通过socket与服务器进行通讯
- C#(服务器)与Java(客户端)通过Socket传递对象
- 两个ESP8266一个作为服务器一个作为客户端实现互相通讯
- Android客户端与PC服务器通过socket进行交互实例
- 【开发笔记】Unity联网斗地主的实现(一,服务器与客户端的数据传递流程)
- C# socket游戏编程(1服务器,多客户端)
- 基于Qt-socketio客户端与Nodejs服务器通讯
- java与 C++ 之间进行 SOCKET 通讯要点简要解析