1. 程式人生 > >unity3D中使用Socket進行資料通訊(三)

unity3D中使用Socket進行資料通訊(三)

          今天跟大家繼續學習下socket,由於最近有個招標引數需要給之前的一款產品做教師端以及後臺資料庫部分,忙了將近兩個禮拜,今天剛釋出了,就繼續我們的socket通訊部分。

         之前服務端一直在VS中去做,考慮到後面客戶端與伺服器一體化,就把服務端也在unity中實現了,需要注意的一點是,由於服務端中包含阻塞方法,而unity所有指令碼都只在僅存的一個主執行緒中執行,所以如果直接在start中呼叫啟動伺服器的方法,unity會直接卡死的,所以我們就自己起一個執行緒去搞服務端部分,unity中起執行緒後要清楚兩點:

1、monoBehavior類中的方法儘量別用了,會出現不可預知的

bug

2、自己起的執行緒,系統不會摻和,自己找個合適的地方再把他kill掉。

         下面的程式碼是在程式結束時殺掉執行緒,想起以前老謝給我講的,起執行緒就像拉屎,完事一定要記得自己擦,系統不會給你擦,經測試不擦第二次啟動unity會無響應。

這一次程式碼裡簡單實現了從客戶端傳送一個字串的包到服務端,服務端接收後並打印出來,程式碼全部貼出來:

1、服務端部分:

using UnityEngine;
using System.Collections;

using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System;
/// <summary>
/// scoket伺服器監聽埠指令碼
/// </summary>
public class SocketServer : MonoBehaviour
{

    private Thread thStartServer;//定義啟動socket的執行緒
    void Start()
    {
        thStartServer = new Thread(StartServer);
        thStartServer.Start();//啟動該執行緒
    }

    void Update()
    {
    }

    private void StartServer()
    {
        const int bufferSize = 8792;//快取大小,8192位元組
        IPAddress ip = IPAddress.Parse("192.168.0.13");

        TcpListener tlistener = new TcpListener(ip, 10001);
        tlistener.Start();
        Debug.Log("Socket伺服器監聽啟動......");

        TcpClient remoteClient = tlistener.AcceptTcpClient();//接收已連線的客戶端,阻塞方法
        Debug.Log("客戶端已連線!local:" + remoteClient.Client.LocalEndPoint + "<---Client:" + remoteClient.Client.RemoteEndPoint);
        NetworkStream streamToClient = remoteClient.GetStream();//獲得來自客戶端的流
        do
        {
            try  //直接關掉客戶端,伺服器端會丟擲異常
            {
                //接收客戶端傳送的資料部分
                byte[] buffer = new byte[bufferSize];//定義一個快取buffer陣列
                int byteRead = streamToClient.Read(buffer, 0, bufferSize);//將資料搞入快取中(有朋友說read()是阻塞方法,測試中未發現程式阻塞)
                if (byteRead == 0)//連線斷開,或者在TCPClient上呼叫了Close()方法,或者在流上呼叫了Dispose()方法。
                {
                    Debug.Log("客戶端連線斷開......");
                    break;
                }

                string msg = Encoding.Unicode.GetString(buffer, 0, byteRead);//從二進位制轉換為字串對應的客戶端會有從字串轉換為二進位制的方法
                Debug.Log("接收資料:" + msg + ".資料長度:[" + byteRead + "byte]");
            }
            catch(Exception ex)
            {
                Debug.Log("客戶端異常:"+ex.Message);
                break;
            }
        }
        while (true);
    }

    void OnApplicationQuit()
    {
        thStartServer.Abort();//在程式結束時殺掉執行緒,想起以前老謝給我講的,起執行緒就像拉屎,完事一定要記得自己擦,系統不會給你擦,經測試不擦第二次啟動unity會無響應
    }


}

2、客戶端部分:

using UnityEngine;
using System.Collections;

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

public class SocketClient : MonoBehaviour
{

    void Start()
    {

    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Alpha1))
        {
            Client();
        }
        if (Input.GetKeyDown(KeyCode.Alpha2))
        {
            SimulateMultiUserClient();
        }
    }
    TcpClient client;
    private void Client()
    {
        client = new TcpClient();
        try
        {
            client.Connect(IPAddress.Parse("192.168.0.13"), 10001);//同步方法,連線成功、丟擲異常、伺服器不存在等之前程式會被阻塞
        }
        catch (Exception ex)
        {
            Debug.Log("客戶端連線異常:" + ex.Message);
        }
        Debug.Log("LocalEndPoint = " + client.Client.LocalEndPoint + ". RemoteEndPoint = " + client.Client.RemoteEndPoint);

        //客戶端傳送資料部分
        for (int i = 0; i < 2; i++)
        {
            try
            {
                string msg = "hello server i am No " + i;
                NetworkStream streamToServer = client.GetStream();//獲得客戶端的流
                byte[] buffer = Encoding.Unicode.GetBytes(msg);//將字串轉化為二進位制
                streamToServer.Write(buffer, 0, buffer.Length);//將轉換好的二進位制資料寫入流中併發送
                Debug.Log("發出訊息:" + msg);
            }
            catch(Exception ex)
            {
                Debug.Log("服務端產生異常:"+ex.Message);
            }
        }
    }

    private void SimulateMultiUserClient()
    {
        for (int i = 0; i < 2; i++)
        {
            client = new TcpClient();
            try
            {
                client.Connect(IPAddress.Parse("192.168.0.13"), 10001);//連線到伺服器端
            }
            catch (Exception ex)//丟擲連線錯誤的異常
            {
                Debug.Log("客戶端連線異常:" + ex.Message);
            }
            Debug.Log("LocalEndPoint = " + client.Client.LocalEndPoint + ". RemoteEndPoint = " + client.Client.RemoteEndPoint);
            //客戶端傳送資料部分
            string msg = "hello server i am No " + i;
            NetworkStream streamToServer = client.GetStream();//獲得客戶端的流
            byte[] buffer = Encoding.Unicode.GetBytes(msg);//將字串轉化為二進位制
            streamToServer.Write(buffer, 0, buffer.Length);//將轉換好的二進位制資料寫入流中併發送
            Debug.Log("發出訊息:" + msg);
        }
    }

    private void SendMsgToServer(string content)
    {

    }
}




相關推薦

unity3D使用Socket進行資料通訊

          今天跟大家繼續學習下socket,由於最近有個招標引數需要給之前的一款產品做教師端以及後臺資料庫部分,忙了將近兩個禮拜,今天剛釋出了,就繼續我們的socket通訊部分。          之前服務端一直在VS中去做,考慮到後面客戶端與伺服器一體化,就把服

unity3D使用Socket進行資料通訊

上一篇部落格主要介紹了使用socket搭建服務端和客戶端程式,這一篇來說說socket的資料傳輸,我們使用socket的目的是解決點對點之間的資料傳輸,之前提到了socket中一個重要的概念:埠。而socket傳輸資料的方式就是埠與埠之間以流(stream)的方式傳輸資料,s

管道通訊,使用管道通訊進行資料交流PipeInputStream

想了解一下,管道之間是怎樣進行通訊的,於是看到網上的做的一個Demo,於是記錄下來,方便學習 寫一個訊息生產者 /** * @author chenxihua * @Date 2018年9月17日 * * 我們以數字替代產品 生產者每5秒提供5個產品,放入管道

簡單的通訊----使用Socket實現TCP協議

功能 客戶端向伺服器端傳送一張檔案(這裡以圖片為例),伺服器發反饋訊息給客戶端。 程式碼 package com.demo; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; im

資料爬蟲:pythonrequests庫使用方法詳解

一、什麼是Requests Requests 是⽤Python語⾔編寫,基於urllib,採⽤Apache2 Licensed開源協議的 HTTP 庫。它⽐ urllib 更加⽅便,可以節約我們⼤量的⼯作,完全滿⾜HTTP測試需求。 ⼀句話——Python實現的簡單易

多執行緒通訊多執行緒通知/等待交叉進行

        如何向A、B兩個檔案中寫資料並且向A、B中寫資料是交叉進行的,假定向A中寫資料的是A執行緒,向B中寫資料的是B執行緒,那麼可以通過定義一個標識,用來控制A、B執行緒的交叉效果。定義輸出類public class FileOutput { // 定義v

Go語言進行web開發 Go的WebSocket程式設計

8.2 WebSocket WebSocket是HTML5的重要特性,它實現了基於瀏覽器的遠端socket,它使瀏覽器和伺服器可以進行全雙工通訊,許多瀏覽器(Firefox、Google Chrome和Safari)都已對此做了支援。 在WebSocket出現之前,為

FPGA+DSP SRIO通訊——基於LSU的資料傳輸

之前的配置中我們知道如何配置通道速率、設定deviceID。 也就是馬路已經鋪設好了,我們應該造車了。 搏一搏,單車變摩托! SRIO不是單車,而是摩托車,我們需要搏一搏,把這個摩托車造出來,在我們已經鋪設好的高速路上飛馳。 目錄 下面提及的

SQL Server 2005的分區表:將普通表轉換成分區表

成了 insert 刪掉 -- pri light part ide 新建 在設計數據庫時,經常沒有考慮到表分區的問題,往往在數據表承重的負擔越來越重時,才會考慮到分區方式,這時,就涉及到如何將普通表轉換成分區表的問題了。 那麽,如何將一個普通表轉換成一個分區表 呢

*使用Centos下的iptables實現實驗室按教室、按時間進行上網控制

Linux 高校運維 iptables 上網時間控制 本章介紹如何使用time模塊對教室上網進行控制,以206教室為例,206教室網絡屬於Vlan206,net:10.1.26.0/24,gateway:10.1.26.254 206文件; #ALL#iptables -A FORWARD

3PPS、PR、PDF編輯器Acrobat的基基本操作

確認密碼 安全性 inf 選中 編輯器 png nbsp 打開 順序 本文介紹一些關於圖片、視頻、PDF的最常用操作: 圖像方面:旋轉、裁剪、拼接、水印(文字)、導出     軟件:Photoshop 視頻方面:剪切(拼接)、水印(文字、字幕)、導出    軟件:Premi

認證鑑權與API許可權控制在微服務架構的設計與實現

引言: 本文系《認證鑑權與API許可權控制在微服務架構中的設計與實現》系列的第三篇,本文重點講解token以及API級別的鑑權。本文對涉及到的大部分程式碼進行了分析,歡迎訂閱本系列文章。 1. 前文回顧 在開始講解這一篇文章之前,先對之前兩篇文章進行回憶下。在第一篇 認證鑑權與AP

PythonFlask的基礎入門

如果我們想要在flask中用到資料庫,那麼我們需要配置。 下面我們有mysql為例來配置 首先你的電腦上要有一個mysql資料庫,然後才可以。 下面是我們配置的程式碼 from flask import Flask,render_template from flask_sqlal

資料結構:線性表

一、線性表及其邏輯結構 1、線性表的定義 線性表是具有相同特性的資料元素的一個有限序列。 該序列中所含的元素個數叫做線性表的長度,用 n表示(n>=0)。當 n=0時,表示線性表是一個空表,即表中不包含任何資料元素。 線性表中的第一個元素叫做表頭元素,最後一

JDKJCA的簡單使用---RSA加密解密

Cipher 類 Cipher類提供用於加密和解密的加密密碼功能。加密是獲取資料(稱為明文)和 金鑰,並且生成資料(密文)對於不知道金鑰的第三方無意義的過程。解密是一個相反的過程:採用密文和金鑰並生成明文。 對稱與非對稱加密 有兩種主要的加密型別:對稱(也稱為金鑰)和非對稱(或公

資料結構之棧

棧是後進先出,先進後出 棧是一種受限制的線性表,只允許一端插入和刪除資料。 棧的實現也有兩種,用陣列實現叫順序棧;用連結串列實現叫鏈式棧。 // 基於陣列實現的順序棧 public class ArrayStack { private String[] items; // 陣列 private i

智慧汽車無人駕駛資料調研

資料來源:長江證券 1.1 長江證券 2015/12  邏輯思路類似:IT 企業和汽車企業選擇路徑有所差異。IT 企業使用鐳射雷達+高精地圖+人工智慧直接實現無人駕駛,汽車企業將從輔助駕駛逐步進入自動駕駛。不管哪條路徑,智慧和網聯是實現汽車高度自動化的基礎,單車的智慧將先行與交通的智慧。以環境感知和電控執行

程序間通訊共享記憶體

概念: 共享記憶體區是最快的IPC形式。⼀一旦這樣的記憶體對映到共享它的程序的地址空間,這些程序間資料傳遞不再 涉及到核心,換句話說是程序不再通過執⾏行進⼊入核心的系統調⽤用來傳遞彼此的資料。 共享記憶體中的函式: shmget函式: 功能:⽤用來建立共享記憶體 原型

Android IPC程序間通訊Binder

程序間通訊的介質Binder Binder實現了IBinder介面,是android中跨程序通訊的一種方式。是服務端和客戶端通訊的媒介。 Binder的建立: 1.建立自定義類Book.java實現Parcelable介面,以實現序列化可反序列化。 public class Book

Android手機通過wifi進行資料傳輸

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!