由于项目需要, 我需要通过 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, ); //异步连接,连接成功调用connectCallback方法
IAsyncResult result = socket.BeginConnect(endpoint, new AsyncCallback(ConnectCallback), socket); //这里做一个超时的监测,当连接超过5秒还没成功表示超时
bool success = result.AsyncWaitHandle.WaitOne(, 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[];
int i = socket.Receive(bytes);
if (i <= )
{
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, , msg.Length, SocketFlags.None, new AsyncCallback(SendCallback), socket);
bool success = asyncSend.AsyncWaitHandle.WaitOne(, 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