目录

1.项目说明

2.Socket通信

2.1C#实现socket通信

2.2python实现socket通信

3.结果

3.1C#socket通信结果

3.2python和C# socket通信结果


1.项目说明

项目使用unity3D搭建环境,并通过python程序控制unity环境。在控制过程中,需要使用socket通信将python处理后的数据发送到unity环境中。由于第一次接触socket通信,因此,首先使用C#搭建了客户端和服务器端进行实验,然后使用python搭建服务器,C#搭建客户端进行实验,最后在unity上进行测试。由于unity和python程序都运行在同一台电脑上,我们使用IP地址为127.0.0.1。整个通信过程是,建立连接后,客户端向服务器端发送字符串“location”,服务器端接收到字符串后,将一个坐标发送到客户端。

2.Socket通信

Socket封装了TCP/IP协议,可以视为TCP/IP协议向程序员开发所提供的接口,从而简化了网络编程。Socket在网络通信中的位置如图所示。

2.1C#实现socket通信

我们使用的是异步socket通信,主要流程为建立socket连接,收发数据,关闭连接。

(1)引入命名空间

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;

(2)建立socket对象和事件状态

由于异步通信,当socket进行通信时,主线程将会执行后面的内容。但后面的程序可能需要在 socket通信之后才能进行,因此需要事件状态来阻塞主线程的运行。

public Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);public static ManualResetEvent allDone = new ManualResetEvent(false);private static ManualResetEvent receiveDone =new ManualResetEvent(false);private static ManualResetEvent connectDone = new ManualResetEvent(false);private static ManualResetEvent sendDone =new ManualResetEvent(false);private static String response = String.Empty;static void Main(string[] args)

(3)建立socket连接

biginconnect对远程主机发送建立连接的异步请求,这里异步方法除了一般的参数外,还有两个参数,一个是回调函数,另一个是状态对象,状态对象向回调函数提供异步通信的状态,对应于回调函数中的参数IAsyncResult。IAsyncResult是接口,里面有几个属性用来查看可以查看异步操作的状态:AsyncState 获取用户定义的对象,它限定或包含关于异步操作的信息。回调函数主要对后续任务和通信的状态进行处理。回调函数中,应调用 EndConnect 方法。 当应用程序调用 BeginConnect 时,系统将使用单独的线程执行指定的回调方法,并在 EndConnect 上一直阻止到 Socket成功连接或引发异常为止。 此外,我们不希望在建立socket连接时,主线程执行其他任务,因此主线程中使用waitone进行阻塞。当需要原始线程继续执行时,在回调方法中调用ManualResetEvent 的 Set 方法。

string address = "127.0.0.1";IPAddress hostIP = IPAddress.Parse(address);int port = 50088;clientSocket.BeginConnect(hostIP, port, new AsyncCallback(connectCallback), clientSocket);connectDone.WaitOne();private void connectCallback(IAsyncResult asyncConnect){try{Socket client = (Socket)asyncConnect.AsyncState;client.EndConnect(asyncConnect);Console.WriteLine("Socket connected to {0}", client.RemoteEndPoint.ToString());// Signal that the connection has been made.     connectDone.Set();}catch (Exception e){Console.WriteLine(e.ToString());}}

(4)发送数据

在成功建立连接后,客户端向服务器发送字符串“location”,首先将字符串进行ASCII编码,并调用异步方法beginsend发送数据,该异步方法同样有回调函数,对发送状态进行处理,解除主线程的阻塞。

Send(clientSocket, content);sendDone.WaitOne();private static void Send(Socket handler, String data){// Convert the string data to byte data using ASCII encoding.     byte[] byteData = Encoding.ASCII.GetBytes(data);// Begin sending the data to the remote device.     handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);}private static void SendCallback(IAsyncResult ar){try{// Retrieve the socket from the state object.     Socket handler = (Socket)ar.AsyncState;// Complete sending the data to the remote device.     int bytesSent = handler.EndSend(ar);Console.WriteLine("Sent {0} bytes to server.", bytesSent);sendDone.Set();}catch (Exception e){Console.WriteLine(e.ToString());}}

(5)接收数据

服务器接收到“location”后,将坐标(12.3,13.6)发送给客户端。因此客户端开始接收数据。首先创建stateobject对象存放接收的数据对象,然后调用异步方法beginreceive。在回调函数中,由于传送的数据量可能大于buffer容量,因此需要多次读取,才能接收到全部的数据,因此使用if (state.sb.Length > 1)进行判断,如果满足条件,则再次调用beginrreceive方法。

 Receive(clientSocket);receiveDone.WaitOne();
private static void Receive(Socket client){try{// Create the state object.     StateObject state = new StateObject();state.workSocket = client;// Begin receiving the data from the remote device.     Console.WriteLine("async receive location");client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);}catch (Exception e){Console.WriteLine(e.ToString());}}private static void ReceiveCallback(IAsyncResult ar){try{// Retrieve the state object and the client socket     // from the asynchronous state object.     StateObject state = (StateObject)ar.AsyncState;Socket client = state.workSocket;// Read data from the remote device.     int bytesRead = client.EndReceive(ar);if (bytesRead > 0){// There might be more data, so store the data received so far.     state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));// Get the rest of the data.     client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);}else{// All the data has arrived; put it in response.     if (state.sb.Length > 1){response = state.sb.ToString();Console.WriteLine(response.ToString());}// Signal that all bytes have been received.     receiveDone.Set();}}catch (Exception e){Console.WriteLine(e.ToString());}}

(6) 关闭套接字连接

项目中仅需要进行坐标的传递,在接收到坐标后即可关闭套接字连接。clientSocket.Shutdown通知服务器端或客户端停止接收和发送数据,参数SocketShutdown.Both意味着客服端和服务器端都停止。

clientSocket.Shutdown(SocketShutdown.Both);clientSocket.Close();

(7)服务器端

以上操作都是针对客户端的,而服务器端收发数据的操作也大致相同,服务器端和客户端的套接字对应相同的IP和端口,其余主要的区别是套接字建立连接时的操作不同。服务器端需要将套接字和IP端口绑定。BeginAccept开始一个异步操作来接受一个传入的连接尝试。回调函数中,套接字连接成功后,从客户端接收数据,接收到“location”时,再将坐标发送过。

IPAddress local = IPAddress.Parse("127.0.0.1");IPEndPoint iep = new IPEndPoint(local, 50088);server.Bind(iep);server.Listen(100);while (true){allDone.Reset();Console.WriteLine("Waiting for a connection...");server.BeginAccept(new AsyncCallback(Acceptcallback), server);allDone.WaitOne();}
public static void Acceptcallback(IAsyncResult iar){// Signal the main thread to continue.     //还原传入的原始套接字Socket listener = (Socket)iar.AsyncState;//在原始套接字上调用EndAccept方法,返回新的套接字Socket handler = listener.EndAccept(iar);// Create the state object.     StateObject state = new StateObject();state.workSocket = handler;handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);receiveDone.WaitOne();allDone.Set();// Create the state object.     //StateObject state = new StateObject();//state.workSocket = handler;//handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);}

(8)C#代码链接

https://github.com/wzyzyw/Socket

2.2python实现socket通信

python主要介绍关于服务器端的创建。

(1)创建socket对象并绑定IP端口

s=socket.socket()
s.bind(('127.0.0.1',50088))
s.listen()

(2)接收客户端的请求连接

accept()接受一个客户端的连接请求,并返回一个新的套接字,与客户端通信是通过这个新的套接字上发送和接收数据来完成的。

c, addr = s.accept()

(3)从套接字读取数据并发送数据

c.recv(1024).decode('ascii')c.send(str_content.encode('ascii'))

(4)完整python代码

import sockets=socket.socket()
s.bind(('127.0.0.1',50088))
s.listen()
sync_robot_loc=[12.3,13.6]
def def_socket_thread():# global loop# loop = asyncio.get_event_loop()try:while True:c, addr = s.accept()content = read_from_client(c)if content.find('location') > -1:global sync_robot_locprint('receive request')print('sycn position=', sync_robot_loc)x = sync_robot_loc[0]y = sync_robot_loc[1]str_content = 'x=' + str(x) + ',y=' + str(y)c.send(str_content.encode('ascii'))print('finish location send')else:print('no request')except IOError as e:print(e.strerror)print('start socket thread!!!')def read_from_client(c):try:return c.recv(1024).decode('ascii')except IOError as e:# 如果异常的话可能就是会话中断 那么直接删除print(e.strerror)if __name__=='__main__':def_socket_thread()

3.结果

3.1C#socket通信结果

consoleapp1是客户端显示的结果,consoleapp2是服务器端显示的结果,意味着成功实现了socket通信。

3.2python和C# socket通信结果

下图是python服务器端的结果

下图是C#客户端的结果

意味着成功实现了socket通信。

C#和Python的Socket通信相关推荐

  1. python进程socket通信_python实现多进程通信实例分析

    操作系统会为每一个创建的进程分配一个独立的地址空间,不同进程的地址空间是完全隔离的,因此如果不加其他的措施,他们完全感觉不到彼此的存在.那么进程之间怎么进行通信?他们之间的关联是怎样的?实现原理是什么 ...

  2. Python攻防-Socket通信建立TCP反向连接

    文章目录 前言 远程控制 脚本编写 效果演示 脚本优化 getopt () 完整代码 效果演示 前言 本文将记录学习基于 Socket 通信机制建立 TCP 反向连接,借助 Python 脚本实现主机 ...

  3. python进程socket通信_python之socket初识

    本篇文章主要讲的是 socket基本操作.包括 网络通信三要素.TCP三次握手以及socket通信流程等.希望感兴趣的小伙伴可以坚持看下去同时欢迎提出宝贵的意见让我们一起进步! 01:OSI模型 1) ...

  4. python进程socket通信_Python Socket TCP双端聊天功能实现过程详解

    SOCKET编程 socket(套接字):是一个网络通信的端点,能实现不同主机的进程通信, -通过IP+端口定位对方并发送消息的通信机制 分为UDP和TCP 客户端Client: 发起访问的一-方 服 ...

  5. Python下socket通信

    Server端代码: #!/usr/bin/env python # -*- coding: utf-8 -*- # Author: areful# a server example which se ...

  6. python进程socket通信_python3 进程间通信之socket.socketpair()

    python3 进程间通信之socket.socketpair() socket.socketpair()是什么鬼东西? socket.socketpair()函数仅返回两个已经连接的套接字对象,参数 ...

  7. python - udp socket通信循环发送和接收数据

    运行结果:(在测试的过程中udp_client.py中的send_addr要设置为:接收方的IP地址) udp_client.py: #coding=utf-8 import socketdef ma ...

  8. pythonsocket自动化教程_Python基本socket通信控制操作示例

    本文实例讲述了Python基本socket通信控制操作.分享给大家供大家参考,具体如下: python - 基本socket通信控制(控制在celie.txt文件中主机IP地址可以发送信息,并返回对应 ...

  9. 嵌入式开发日记(9)——多线程与socket通信

    尝试用多线程,socket网络编程,心跳检测机制,实时绘图,丢包检测机制,校验位检测,超时重传机制,  数据库存储等功能优化项目 多线程与socket编程: 参考链接: https://blog.cs ...

最新文章

  1. 一个命令让Ubuntu升级变得更简单
  2. 为什么Python的“私有”方法实际上不是私有的?
  3. 菜鸟崛起 DB Chapter 2 MySQL 5.6的概述与安装
  4. 关于mysql报 loopWaitCount 0, wait millis 60000 错误的解决办法
  5. React Native ScrollableTabView的自定义tabBar
  6. Android开发之Android studio代码版本回退教程
  7. 使用基本身份验证来保护Spring Boot REST API
  8. oracle ogg 12安装,Oracle GoldenGate Studio 12.2.1.3安装
  9. RandomCodeUtil随机数工具类,随机生成数字、字母、数字字母组合、中文姓名
  10. halcon安装教程
  11. 单片机实验五、外部中断实验
  12. 零基础数据挖掘入门-二手车价格预测part(一):EDA-数据探索性分析
  13. 备战金九银十!2022Java面试必刷461道大厂架构面试真题汇总+面经+简历模板都放这了,注意划重点!!
  14. 使用Pytorch识别字符验证码
  15. 0xE06D7363: Microsoft C++ Exception.
  16. 潜藏在手机中的新威胁:免安装应用安全指北
  17. 手把手教你拥有自己的代码生成器-------->坑居多
  18. python什么是形参?
  19. 解决Linux上WPS字体缺失问题
  20. python 素数库_使用Python判断质数(素数)的简单方法讲解

热门文章

  1. github java排课系统_团队-排课系统-开发文档
  2. 对话系统(任务型、检索式、生成式对话论文与工具串讲)
  3. 时间加权平均价格算法(TWAP)和成交量平均算法(VWAP)在量化回测的应用
  4. ArcGIS Pro:OSGB数据转换及发布服务流程
  5. android proxydroid代理
  6. 谷歌云应用欲来,风满楼
  7. 【笔记】Logstash环境搭建和安装配置
  8. 华为日历怎么显示一月_南京百达翡丽服务去哪里表蒙摔碎了怎么办
  9. 按生辰八字给马宝宝取名的注意事项
  10. 雷达感应模组,自动播放讲解仪雷达应用,雷达传感器技术