【转】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

愿你我既可以朝九晚五,也可以浪迹天涯;愿你我既可以拈花把酒,也能围炉诗书茶。
原文地址:https://www.cnblogs.com/xiaoheihei/p/13866271.html