开源Agent OS项目OpenFang:让AI直接操作电脑,告别复制粘贴
2026/10/23 9:27:29
using System; using System.Net; using System.Net.Sockets; using System.Text; namespace TeachTcpServer { class Program { static void Main(string[] args) { #region 服务端需要做的事情 //1.创建套接字Socket //2.用Bind方法将套接字与本地地址绑定 //3.用Listen方法监听 //4.用Accept方法等待客户端连接 //5.建立连接,Accept返回新套接字 //6.用Send和Receive相关方法收发数据 //7.用Shutdown方法释放连接 //8.关闭套接字 #endregion #region 实现服务端基本逻辑 //1.创建套接字Socket(TCP) Socket socketTcp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //2.用Bind方法将套接字与本地地址绑定 try { IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8080); socketTcp.Bind(ipPoint); } catch (Exception e) { Console.WriteLine("绑定报错" + e.Message); return; } //3.用Listen方法监听 socketTcp.Listen(1024); Console.WriteLine("服务端绑定监听结束,等待客户端连入"); //4.用Accept方法等待客户端连接 //5.建立连接,Accept返回新套接字 Socket socketClient = socketTcp.Accept(); Console.WriteLine("有客户端连入了"); //6.用Send和Receive相关方法收发数据 //发送 socketClient.Send(Encoding.UTF8.GetBytes("欢迎连入服务端")); //接受 byte[] result = new byte[1024]; //返回值为接受到的字节数 int receiveNum = socketClient.Receive(result); Console.WriteLine("接受到了{0}发来的消息:{1}", socketClient.RemoteEndPoint.ToString(), Encoding.UTF8.GetString(result, 0, receiveNum)); //7.用Shutdown方法释放连接 socketClient.Shutdown(SocketShutdown.Both); //8.关闭套接字 socketClient.Close(); #endregion #region 总结 //1.服务端开启的流程每次都是相同的 //2.服务端的 Accept、Send、Receive是会阻塞主线程的,要等到执行完毕才会继续执行后面的内容 //引出问题: //如何让服务端可以服务n个客户端? #endregion Console.WriteLine("按任意键退出"); Console.ReadKey(); } } }using System; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; namespace TeachTcpServerExercises { class Program { static Socket socket; //用于存储 客户端连入的 Socket 之后可以获取他们来进行通信 static List<Socket> clientSockets = new List<Socket>(); static bool isClose = false; static void Main(string[] args) { //1.建立Socket 绑定 监听 socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8080); socket.Bind(ipPoint); socket.Listen(1024); //2.等待客户端连接(这节课需要特别处理的地方) Thread acceptThread = new Thread(AcceptClientConnect); acceptThread.Start(); //3.收发消息(这节课需要特别处理的地方) Thread receiveThread = new Thread(ReceiveMsg); receiveThread.Start(); //4.关闭相关 while (true) { string input = Console.ReadLine(); //定义一个规则 关闭服务器 断开所有连接 if (input == "Quit") { isClose = true; for (int i = 0; i < clientSockets.Count; i++) { clientSockets[i].Shutdown(SocketShutdown.Both); clientSockets[i].Close(); } clientSockets.Clear(); break; } //定义一个规则 广播消息 就是让所有客户端收到服务端发送的消息 else if (input.Substring(0, 2) == "B:") { for (int i = 0; i < clientSockets.Count; i++) { clientSockets[i].Send(Encoding.UTF8.GetBytes(input.Substring(2))); } } } } static void AcceptClientConnect() { while (!isClose) { Socket clientSocket = socket.Accept(); clientSockets.Add(clientSocket); clientSocket.Send(Encoding.UTF8.GetBytes("欢迎你连入服务端")); } } static void ReceiveMsg() { Socket clientSocket; byte[] result = new byte[1024 * 1024]; int receiveNum; int i; while (!isClose) { for (i = 0; i < clientSockets.Count; i++) { clientSocket = clientSockets[i]; //判断 该socket是否有可以接收的消息 返回值就是字节数 if (clientSocket.Available > 0) { //客户端即使没有发消息过来 这句代码也会执行 receiveNum = clientSocket.Receive(result); //如果直接在这收到消息 就处理 可能造成问题 //不能够即使的处理别人的消息 //为了不影响别人消息的处理 我们把消息处理 交给新的线程,为了节约线程相关的开销 我们使用线程池 ThreadPool.QueueUserWorkItem(HandleMsg, (clientSocket, Encoding.UTF8.GetString(result, 0, receiveNum))); } } } } static void HandleMsg(object obj) { (Socket s, string str) info = ((Socket s, string str))obj; Console.WriteLine("收到客户端{0}发来的信息:{1}", info.s.RemoteEndPoint, info.str); } } }using System.Collections; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Text; using UnityEngine; public class Lesson6 : MonoBehaviour { // Start is called before the first frame update void Start() { #region 回顾客户端需要做的事情 //1.创建套接字Socket //2.用Connect方法与服务端相连 //3.用Send和Receive相关方法收发数据 //4.用Shutdown方法释放连接 //5.关闭套接字 #endregion #region 实现客户端基本逻辑 //1.创建套接字Socket Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //2.用Connect方法与服务端相连 //确定服务端的IP和端口 IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8080); //服务端运行在本机的ip地址 try { socket.Connect(ipPoint); } catch (SocketException e) { if (e.ErrorCode == 10061) print("服务器拒绝连接"); else print("连接服务器失败" + e.ErrorCode); return; } //3.用Send和Receive相关方法收发数据 //接收数据 byte[] receiveBytes = new byte[1024]; int receiveNum = socket.Receive(receiveBytes); print("收到服务端发来的消息:" + Encoding.UTF8.GetString(receiveBytes, 0, receiveNum)); //发送数据 socket.Send(Encoding.UTF8.GetBytes("你好,我是阿达的客户端")); //4.用Shutdown方法释放连接 socket.Shutdown(SocketShutdown.Both); //5.关闭套接字 socket.Close(); #endregion #region 总结 //1.客户端连接的流程每次都是相同的 //2.客户端的 Connect、Send、Receive是会阻塞主线程的,要等到执行完毕才会继续执行后面的内容 //引出问题: //如何让客户端的Socket不影响主线程,并且可以随时收发消息? #endregion } // Update is called once per frame void Update() { } }using System.Collections; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using UnityEngine; public class NetMgr : MonoBehaviour { private static NetMgr instance; public static NetMgr Instance => instance; //客户端Socket private Socket socket; //用于发送消息的队列 公共容器 主线程往里面放 发送线程从里面取 private Queue<string> sendMsgQueue = new Queue<string>(); //用于接收消息的对象 公共容器 子线程往里面放 主线程从里面取 private Queue<string> receiveQueue = new Queue<string>(); //用于收消息的水桶(容器) private byte[] receiveBytes = new byte[1024 * 1024]; //返回收到的字节数 private int receiveNum; //是否连接 private bool isConnected = false; void Awake() { instance = this; DontDestroyOnLoad(this.gameObject); } // Update is called once per frame void Update() { if (receiveQueue.Count > 0) { print(receiveQueue.Dequeue()); } } //连接服务端 public void Connect(string ip, int port) { //如果是连接状态 直接返回 if (isConnected) return; if (socket == null) socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //连接服务端 IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse(ip), port); try { socket.Connect(ipPoint); isConnected = true; //开启发送线程 ThreadPool.QueueUserWorkItem(SendMsg); //开启接收线程 ThreadPool.QueueUserWorkItem(ReceiveMsg); } catch (SocketException e) { if (e.ErrorCode == 10061) print("服务器拒绝连接"); else print("连接失败" + e.ErrorCode + e.Message); } } //发送消息 public void Send(string info) { sendMsgQueue.Enqueue(info); } private void SendMsg(object obj) { while (isConnected) { if (sendMsgQueue.Count > 0) { socket.Send(Encoding.UTF8.GetBytes(sendMsgQueue.Dequeue())); } } } //不停的接受消息 private void ReceiveMsg(object obj) { while (isConnected) { if (socket.Available > 0) { receiveNum = socket.Receive(receiveBytes); //收到消息 解析消息为字符串 并放入公共容器 receiveQueue.Enqueue(Encoding.UTF8.GetString(receiveBytes, 0, receiveNum)); } } } public void Close() { if (socket != null) { socket.Shutdown(SocketShutdown.Both); socket.Close(); isConnected = false; } } private void OnDestroy() { Close(); } }