zoukankan      html  css  js  c++  java
  • 【转】Java 服务端 和 C# 客户端 实现 Socket 通信

    【转自苍之弦 https://www.cnblogs.com/unityworld/p/11345431.html】

    由于项目需要, 我需要通过 Java 开发的服务端对 C# 作为脚本语言开发的 unity 项目实现控制

     话不多说, 直接上代码

    首先, 我们先来构建服务端的代码, 服务端我们使用 Java 语言

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    /*
     *@Description //TODO Socket 服务端$
     *@Author 吾王剑锋所指 吾等心之所向
     *@Date 2019/8/20 14:42
     */
    public class SocketServer {
        private static Logger LOGGER = LoggerFactory.getLogger(SocketServer.class);
    
        private static SocketServer instance = null;
        private boolean flag = true;public void start(){
            new Thread(new SocketThread(), "socket server").start();
            while (!flag) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    LOGGER.error(e.getMessage(), e);
                }
            }
        }
    }

    上面这段代码作为一个开关, 负责启动 socket 服务

    接着, 我们来写一个线程,  负责在服务启动后监听 port 端口发来的连接请求

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import java.net.ServerSocket;
    import java.net.Socket;
    
    /*
     *@Description //TODO socket 通信线程$
     *@Author 吾王剑锋所指 吾等心之所向
     *@Date 2019/8/19 14:49
     */
    public class SocketThread implements Runnable {
        private static Logger LOGGER = LoggerFactory.getLogger(SocketThread.class);
    
        private static final Integer port = 5656;
    
        @Override
        public void run() {
            ServerSocket serverSocket = null;
            try{
                serverSocket = new ServerSocket(port);
                LOGGER.info("socket server start, monitor 5656 port ! ");
                Socket socket = serverSocket.accept();
                new SocketClientRequest(socket).start();
                LOGGER.info("send success ! ");
            }catch (Exception ex){
                LOGGER.error("send fail ! ");
            }
    
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                LOGGER.error("Server delayed restart failed ! ");
            }
        }
    }

    接着, 再写一个线程, 负责在监听到连接后, 接收客户端发来的信息客户端发送信息

     
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import java.io.BufferedInputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.net.Socket;
    
    /*
     *@Description //TODO socket 客户端请求线程$
     *@Author 吾王剑锋所指 吾等心之所向
     *@Date 2019/8/20 14:54
     */
    public class SocketClientRequest extends Thread{
        private static Logger LOGGER = LoggerFactory.getLogger(SocketClientRequest.class);
    
    
        private int messageLengthBytes = 1024;
        public Socket socket;
        private BufferedInputStream bufferedInputStream = null;
    
        public SocketClientRequest(Socket socket) {
            this.socket = socket;
        }
    
        @Override
        public void run() {
            try {
                //获取socket中的数据
                bufferedInputStream = new BufferedInputStream(socket.getInputStream());
                byte[] clientCharStream = new byte[messageLengthBytes];
    
                bufferedInputStream.read(clientCharStream);
                System.out.println(new String(clientCharStream, "utf-8"));
    
                OutputStream(socket); //发送信息到客户端
            } catch (IOException e) {
                LOGGER.error("read massage error [{}]", e);
            }
        }
    
        /**
         * 向客户端发送指定信息
         * */
        private static void OutputStream(Socket socket) throws IOException {
            OutputStream out = socket.getOutputStream();
            out.write(new String("welcome_send_server!").getBytes());
        }
    }

    到这里,  socket 的服务端代码就搞定了, 接着, 我们来写客户端的代码

    客户端我使用 unity 作为客户端程序, 所以用C#作为客户端的编程语言

    因为知识做一个实验, 所以随随便便新建一个项目就行了

     

     在文件夹处新建一个 script 文件夹, 用于保存程序文件, 然后在建两个C#文件, 双击打开

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading;
    using UnityEngine;
    
    public class SocketUtils{
    
        private static SocketUtils socketUtils = new SocketUtils();
        private Socket socket;
        //单例模式
        public static SocketUtils GetInstance()
        {
            return socketUtils;
        }
    
        private SocketUtils()
        {
            //采用TCP方式连接
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //服务器IP地址
            IPAddress address = IPAddress.Parse("127.0.0.1");
            //服务器端口
            IPEndPoint endpoint = new IPEndPoint(address, 5566);
            //异步连接,连接成功调用connectCallback方法
            IAsyncResult result = socket.BeginConnect(endpoint, new AsyncCallback(ConnectCallback), socket);
            //这里做一个超时的监测,当连接超过5秒还没成功表示超时
            bool success = result.AsyncWaitHandle.WaitOne(5000, true);
            if (!success)
            {
                //超时
                Closed();
                Debug.Log("connect Time Out");
            }
            else
            {
                //与socket建立连接成功,开启线程接受服务端数据。
                Thread thread = new Thread(new ThreadStart(ReceiveSorket));
                thread.IsBackground = true;
                thread.Start();
            }
    
        }
    
        private void ConnectCallback(IAsyncResult asyncConnect)
        {
            Debug.Log("connect success");
        }
    
        private void ReceiveSorket()
        {
            //在这个线程中接受服务器返回的数据
            while (true)
            {
    
                if (!socket.Connected)
                {
                    //与服务器断开连接跳出循环
                    Debug.Log("Failed to clientSocket server.");
                    socket.Close();
                    break;
                }
                try
                {
                    //接受数据保存至bytes当中
                    byte[] bytes = new byte[4096];
                    int i = socket.Receive(bytes);
                    if (i <= 0)
                    {
                        socket.Close();
                        break;
                    }
                    Debug.Log(System.Text.Encoding.Default.GetString(bytes));
                }
                catch (Exception e)
                {
                    Debug.Log("Failed to clientSocket error." + e);
                    socket.Close();
                    break;
                }
            }
        }
    
        //关闭Socket
        public void Closed()
        {
            if (socket != null && socket.Connected)
            {
                socket.Shutdown(SocketShutdown.Both);
                socket.Close();
            }
            socket = null;
        }
        //向服务端发送一条字符
        public void SendMessage(string str)
        {
            byte[] msg = Encoding.UTF8.GetBytes(str);
    
            if (!socket.Connected)
            {
                socket.Close();
                return;
            }
            try
            {
                IAsyncResult asyncSend = socket.BeginSend(msg, 0, msg.Length, SocketFlags.None, new AsyncCallback(SendCallback), socket);
                bool success = asyncSend.AsyncWaitHandle.WaitOne(5000, true);
                if (!success)
                {
                    socket.Close();
                    Debug.Log("Failed to SendMessage server.");
                }
            }
            catch
            {
                Debug.Log("send message error");
            }
        }
    
        private void SendCallback(IAsyncResult asyncConnect)
        {
            Debug.Log("send success");
        }
    }

    然后是

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class SocketMain : MonoBehaviour {
        void Start () {
            //创建socket连接
            SocketUtils s = SocketUtils.GetInstance();
            //发送信息向服务器端
            s.SendMessage("啦啦啦");
        }
    }

    再将 SocketMain.cs 挂载到相机上

     

    这样子, 服务端客户端就简单的实现了 socket 连接

     先启动服务端

    socket 服务端启动成功,  接着启动客户端

     

    客户端已经成功收到服务端发来的信息

     

    服务端也接受到了客户端的信息

    这样子, 一个简单的双工通讯就新建成功了

    但是这样的系统还有很多问题没有解决, 

    例如: service 层要怎么调用 socket 实现主动控制服务端客户端发送信息呢?

    于是我决定使用netty来做一次升级, 因为netty的框架还提供了很多别的功能, 使得整个通讯系统变得更加的健壮, 

    详情跳转我的另一篇博文 https://www.cnblogs.com/unityworld/p/11425180.html

    愿你我既可以朝九晚五,也可以浪迹天涯;愿你我既可以拈花把酒,也能围炉诗书茶。
  • 相关阅读:
    Pycharm中导入Python包的方法
    关于SOA架构设计的案例分析
    浅谈12306核心模型设计思路和架构设计
    美图数据统计分析平台架构演进
    有赞搜索系统的架构演进
    美团云的网络架构演进之路
    数据蜂巢架构演进之路
    1号店电商峰值与流式计算
    京东B2B业务架构演变
    饿了么:业务井喷时订单系统架构的演进
  • 原文地址:https://www.cnblogs.com/xiaoheihei/p/13866271.html
Copyright © 2011-2022 走看看