2013-04-23 00:06:15 spiritring 阅读数 7227

今天研究了一天.终于把这套东西给搞通了.其实很简单.需要的代码也不是很多...就是中间走了不少弯路.

Node.js端.需要的库就是我LighterWebEngine的TCP封装. 可以去我的Github上面下载,

var tcp = require("./LighterWebEngine/TCP");

tcp.CreateServer(10000,
    function(){ //初始化回调

    },
    function(hSocket, sBuffer){ //有客户端发送消息过来.. sBuffer就是数据. 
        console.log(sBuffer.toString()); //打印客户端发来的消息 "join success!"
    },
    function(hSocket){ //和客户端断开连接

    },
    function(hSocket){ //连接成功
        hSocket.write('hello World!'); //发送给客户端一个 "hello world"
        hSocket.end();
    }
);

unity3d这边其实非常简单..mono就是c#嘛..c#有个tcpclient库.直接加载就可以使用了哈.

using System.Net.Sockets; 
using System.Text;

需要先using该两个命名空间.

TcpClient tcpClient = new TcpClient(); //创建一个本地连接 端口是10000的
tcpClient.Connect("127.0.0.1", 10000);

NetworkStream clientStream = tcpClient.GetStream(); //获取stream. 通过stream可以收数据和发数据
byte[] message = new byte[4096];
int bytesRead;
bytesRead = 0;
bytesRead = clientStream.Read(message, 0, 4096); //收到数据 "hello world!"

UTF8Encoding encoder = new UTF8Encoding();
MonoBehaviour.print(encoder.GetString(message, 0, bytesRead)); //转化数据为utf8字符串并打印出来

byte[] outStream = Encoding.UTF8.GetBytes("joining success!"); //发送一个加入成功的包给服务器.
clientStream.Write(outStream, 0, outStream.Length);
clientStream.Flush();

tcpClient.Close(); //关闭连接

有什么问题可以给我留言. 太晚了睡觉了 see you 孤独拜.!




2017-09-20 17:51:17 BattleTiger 阅读数 904

TCP的特性
1.TCP只会寻址一次
2.TCP 是有序的
3.TCP链接的时候有三次握手 如图
这里写图片描述

4.TCP断开链接的时候需要四次握手 如图
这里写图片描述

整体流程
这里写图片描述

服务端

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//引用两个命名空间
using System.Net;
using System.Net.Sockets;
using System;
//引用线程的命名空间
using System.Threading;

public class SocketState
{
    Socket ClientSocket;
    /// <summary>
    /// 存放接收到的字节流
    /// </summary>
    byte[] ReciveDataBytes = new byte[1024];
    public SocketState(Socket temSocket)
    {
        ClientSocket = temSocket;
    }
    /// <summary>
    /// 客户端向服务器端的链接请求
    /// </summary>
    public void ConnectRequest(string ip,int port)
    {
        IPEndPoint IP = new IPEndPoint(IPAddress.Parse(ip),port);
        ClientSocket.BeginConnect(IP, ConnectCallBack,null);
    }
    /// <summary>
    /// 发送链接请求的回调函数
    /// </summary>
    /// <param name="ar"></param>
    public void ConnectCallBack(IAsyncResult ar)
    {
        //ClientSocket.EndSend(ar)   表示跟服务器成功连接
        ClientSocket.EndConnect(ar);
    }
    /// <summary>
    /// 发送函数
    /// </summary>
    /// <param name="buffer">发送的字节流</param>
    public void SendData(byte[] buffer)
    {

        //发送
        //buffer  发送的字节流
        //0 偏移量 从buffer第0个字节开始
        //buffer.Length 读取长度为buffer的长度
        //SocketFlags.None 
        //SendCallBack 回调函数
        ClientSocket.BeginSend(buffer,0,buffer.Length,SocketFlags.None, SendCallBack,null);Debug.Log(buffer.Length);
    }
    /// <summary>
    /// 发送成功的回调函数
    /// </summary>
    /// <param name="ar"></param>
    public void SendCallBack(IAsyncResult ar)
    {
        //ClientSocket.EndSend(ar) 返回值类型为int  表示成功发送了多少个字节流
        int SendCount = ClientSocket.EndSend(ar);
        Debug.Log("send" + SendCount);
    }
    /// <summary>
    /// 接收函数
    /// </summary>
    /// <param name="buffer">发送的字节流</param>
    public void ReciveData()
    {
        //接收
        //ReciveDataBytes  接收的字节流
        //0 偏移量 从ReciveDataBytes第0个字节开始
        //ReciveDataBytes.Length 读取长度为ReciveDataBytes的长度
        //SocketFlags.None 
        //ReciveCallBack 回调函数
        ClientSocket.BeginReceive(ReciveDataBytes,0, ReciveDataBytes.Length,SocketFlags.None, ReciveCallBack, null);
    }
    /// <summary>
    /// 接收成功的回调函数
    /// </summary>
    /// <param name="ar"></param>
    public void ReciveCallBack(IAsyncResult ar)
    {
        //ClientSocket.EndSend(ar) 返回值类型为int  表示成功接收了多少个字节流
        int ReciveCount = ClientSocket.EndReceive(ar);
        Debug.Log("ReciveCount" + ReciveCount);
    }
}
public class TCPSever : MonoBehaviour {


    Socket severSocket;
    /// <summary>
    /// 端口号  和此端口号绑定
    /// </summary>
    public int port = 18001;
    /// <summary>
    /// 声明一个线程
    /// </summary>
    private Thread TemThread;
    /// <summary>
    /// 线程控制
    /// </summary>
    private bool IsRuningRecive = true;
    /// <summary>
    /// 存放客户端的映射
    /// </summary>
    List<SocketState> ClientSocketList;
    public void Init()
    {

        //AddressFamily 表示地址协议族 IPV4  IPV6
        //SocketType.Stream 数据报格式----> TCP
        //ProtocolType.Tcp  采用的哪种协议 
        severSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
        //获得一个ip
        IPEndPoint ip = new IPEndPoint(IPAddress.Any, port);
        //绑定ip
        severSocket.Bind(ip);
        //实例化线程
        TemThread = new Thread(ReciveThread);
        //开启线程
        TemThread.Start();
        //实例化List
        ClientSocketList = new List<SocketState>();
    }
    /// <summary>
    /// 接收线程
    /// </summary>
    public void ReciveThread()
    {
        while (IsRuningRecive)
        {
            //异步 接收
            //ReciveCallBack  回调函数
            //null 如果不需要就传null就可以了
            severSocket.BeginAccept(ReciveCallBack,null);
            //每隔100毫秒监听一次是否有客户端发送请求
            Thread.Sleep(100);
        }
    }
    /// <summary>
    /// 回调函数  有客户端请求就会调用
    /// </summary>
    /// <param name="ar"></param>
    public void ReciveCallBack(IAsyncResult ar)
    {
        //severSocket.EndAccept(ar.AsyncState) 返回值就是客户端的映射  需要我们保存下来
        Socket ClientSocket = severSocket.EndAccept(ar);
        //实例化一个SocketState
        SocketState temSocketState = new SocketState(ClientSocket);
        //添加到List
        ClientSocketList.Add(temSocketState);
    }

    // Use this for initialization
    void Start () {
        Init();
    }

    // Update is called once per frame
    void Update () {
        //不断的请求询问客户端
        for (int i = 0; i < ClientSocketList.Count; i++)
        {
            ClientSocketList[i].ReciveData();
        }
    }
}

客户端

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//引用两个命名空间
using System.Net;
using System.Net.Sockets;

public class TCPClient : MonoBehaviour {

    SocketState clientSocket;
    // Use this for initialization
    void Start () {
        Socket temSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);

        clientSocket = new SocketState(temSocket);

        clientSocket.ConnectRequest("127.0.0.1",18001);    
    }

    // Update is called once per frame
    void Update () {


        if (Input.GetMouseButtonDown(0))
        {
            byte[] temB = System.Text.Encoding.Default.GetBytes("123456");
            clientSocket.SendData(temB);
        }
        if (clientSocket != null)
        {
            clientSocket.ReciveData();
        }
    }
}
2014-09-01 11:26:28 mysocketclient 阅读数 2952

请邮件联系:mysocketclient@qq.com


国内插件价格¥30,可支付宝付款,不出售源码.

也可以通过unity官方商店购买,$9.9 
 

桌面平台支持:pc, linux, mac

移动平台支持ios, Android, wp

(也可以用在以下平台,但未经过兼容测试:xbox,ps4,黑莓..)


自动拆包粘包支持,支持jit编译,支持wp异步模式 


在unity中使用方法如下(是不是非常简便):
 

更多说明文档及示例代码:https://github.com/hiramtan/HiSocket

2014-11-03 16:35:31 AngelMyMei 阅读数 13915

---------------------------客户端----------------------------------------

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


/*
 * 
 *Socket客户端通信类
 * 
 * lm
 */
public class SocketHelper
{

    private static SocketHelper socketHelper=new SocketHelper();

    private Socket socket;


    //饿汉模式
    public static SocketHelper GetInstance()
    {
        return socketHelper;
    }

    private SocketHelper() {

        //采用TCP方式连接
        socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        //服务器IP地址
        IPAddress address = IPAddress.Parse("127.0.0.1");

        //服务器端口
        IPEndPoint endpoint = new IPEndPoint(address,8000);

        //异步连接,连接成功调用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];
                //Receive方法中会一直等待服务端回发消息
                //如果没有回发会一直在这里等着。
                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");
    }


}

----------------------------------服务器-------------------------------------------------

package org.u3d.server;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;


/**
 * 
 * unity3d 服务端
 * 
 * 
 * 
 * @author lm
 *
 */
public class U3dServer implements Runnable {

	public void run() {
		
		ServerSocket u3dServerSocket = null;

		while(true){
			
			try {
				
				u3dServerSocket=new ServerSocket(8000);
				
				System.out.println("u3d服务已经启动,监听8000端口");
				
				while (true) {
					Socket socket = u3dServerSocket.accept();
					System.out.println("客户端接入");
					new RequestReceiver(socket).start();
				}
				
				
			} catch (IOException e) {
				System.err.println("服务器接入失败");
				if (u3dServerSocket != null) {
					try {
						u3dServerSocket.close();
					} catch (IOException ioe) {
					}
					u3dServerSocket = null;
				}
			}
			
			// 服务延时重启
			try {
				Thread.sleep(5000);
			} catch (InterruptedException e) {

			}
			
		}
		
		
	}
	
	
	
	/**
	 * 客户端请求接收线程
	 * @author lm
	 *
	 */
	class RequestReceiver extends Thread {

		/** 报文长度字节数 */
		private int messageLengthBytes = 1024;

		private Socket socket;

		/** socket输入处理流 */
		private BufferedInputStream bis = null;
		

		public RequestReceiver(Socket socket) {
			this.socket = socket;
		}

		@Override
		public void run() {
			try {
				bis = new BufferedInputStream(socket.getInputStream());
				byte[] buf = new byte[messageLengthBytes];
				
				/**
				 * 在Socket报文传输过程中,应该明确报文的域
				 */
				while (true) {
			
					/*
					 * 这种业务处理方式是根据不同的报文域,开启线程,采用不同的业务逻辑进行处理
					 * 依据业务需求而定 
					 */
					//new RequestHandler(socket, buf).start(); 
					bis.read(buf);
					System.out.println(new String(buf,"utf-8"));
					Message msg=new GeneralMessage("i am server");
					msg.write(socket.getOutputStream());
				}
				
			} catch (IOException e) {
				System.err.println("读取报文出错");
			} finally {
				if (socket != null) {
					try {
						socket.close();
					} catch (IOException e) {
					}
					socket = null;
				}
			}
			
		}
	}
	
	
	/**
	 * 描述: 请求处理器
	 * 
	 */
/*	class RequestHandler extends Thread {


		

	}
*/

}
<pre name="code" class="java">public class U3dApplication {
	
	private static U3dApplication instance = null;

	private boolean stop;

	private U3dApplication() {
	}

	public static synchronized U3dApplication getApplication() {
		if (instance == null) {
			instance = new U3dApplication();
		}
		return instance;
	}
	
	public void start() {
		init();
		new Thread(new U3dServer(), "U3d Server").start();

		while (!stop) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
			}
		}
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Runtime.getRuntime().addShutdownHook(new Thread() {
			@Override
			public void run() {
				getApplication().stopMe();
			}
		});
		getApplication().start();
	}
	
	public void stopMe() {
		System.out.println("系统即将关闭...");
	}
	
	
	/**
	 * 初始化系统
	 */
	private void init() {
		
	}

}





2015-09-30 11:41:48 leoleocs 阅读数 21289

今天介绍一下如何在Unity3d下使用WebSocket。
首先介绍一下什么是websocket,以及与socket,和http的区别与联系,然后介绍一下websocket的一些开源的项目。

WebSocket是什么

WebSocket协议是为了实现网络客户端和服务器端全双工通信而引入的一种基于消息帧和TCP的通信机制,这个协议本身的目标是为了在http服务器上引入双向通信的机制,从而克服http单向通信的缺陷(http设计的初衷就不是为了双向通信),其可以在复用http的端口,支持http的代理,认证等,虽然如此,websocket可以独立于http存在。 详细的内容可以参考RFC6455(https://datatracker.ietf.org/doc/rfc6455/)里面有详细的介绍。

那么WebSocket与http,socket有什么区别和联系呢。

  • WebSocket和http
    其实从历史上来讲,websocket是为了克服http无法双向通信而引入的,在通常的使用中,可以复用http的端口与功能,除此外,他们没有其他的联系,而是完全是独立的协议,通常情况下,http是单向的web 服务,而websocket是全双工的,服务器和客户端可以实时的传输信息,在引用时他们可以在http服务器上同时部署,特别是在NodeJs中。
  • WebSocket与Socket
    那么websocket和socket是什么关系呢? 其实可以理解为websocket是在socket的基础上实现的,其基于消息帧和TCP协议,而socket更通用,在编程中,可以选在tcp,udp,也需要自己控制数据流格式,每次的数据的长度都需要自己控制与读取。

Unity3d下如何使用WebSocket

现在越来越多的Unity3d游戏需要使用websocket或者后台的服务,在实际中,NodeJs,SocketIO越来越多的作为后台的服务加以应用,那么在unity3d的前端上可以使用的开源的websocket有两种:

  • UnitySocketIO
    可以参考https://github.com/kaistseo/UnitySocketIO-WebSocketSharp ,其完全是C# dll的方式Unity3d中使用,测试了在windows和linux下使用完全没有问题。分析一下优缺点:
    优点: 直接使用dll,无unity3d的依赖,代码比较好测试,支持多种消息类型,如文本,Json等。
    缺点:需要依赖第三方的库,如SuperSocket,SimpleJson等,在ios下需要单独维护。

  • Socket.IO for unity
    unity3d 的Asset store上有一个免费的开源项目 Socket.IO for unity (https://www.assetstore.unity3d.com/en/#!/content/21721)可以使用。测试了windows和linux版本,没有问题。 其他的andriod和ios应该也没有问题,根据代码和文档。
    优点: 代码直接嵌入到Unity3d中,有所有的源代码,支持Json的消息传输。
    缺点: 写测试用例相对繁琐,Json消息简单,不支持对象的Json解析,不过这块应该可以重写。

Unity3D的Socket通信

阅读数 943

没有更多推荐了,返回首页