Unity3d使用socket传输图片

news/2024/11/29 4:04:19/

C# socket通信只能传输的字节流,所以 我们若是想利用socket传输任何东西,都必须将之以字节的形式进行传输

So 本文就抛砖引玉一下,以传输图片的形式来示范一下,socket传输除文本数据以外的数据   嘻嘻~~~大笑


既然是网络通信,那必然是有客户端和服务器端(通俗点说就是一发一收),那么就先说说客户端的那些事情吧!!!
(ps:如果,不知道客户端是什么的兄弟们,请不要往下看了,先去恶补恶补网络通信的一些知识)

在客户端,如果不说初始化socket那点事,那么,就只做一件事儿,就是将图片转换为字节数据,以便后边用Send函数进行传输,好吧,话不多说,直接上代码
private byte[] fssize; 
FileStream fs = new FileStream("D:/girl.jpg",FileMode.OpenOrCreate,FileAccess.Read);
Msg.fssize = new byte[fs.Length];
BinaryReader strread = new BinaryReader(fs);
strread.Read(Msg.fssize,0,Msg.fssize.Length);
上边4行代码做了这么几件事情:
1.定义一个需要被传输的字节数组fssize
2.创建FileStream对象,并基于该对象创建了BinaryReader对象
3.调用BinaryReader下的Read方法将数据读入fssize数组里边


当然,个个函数的具体参数是什么意思,我这里不展开阐述,查查MSDN就明白就可以了解的
我这里是将D盘的一张名为girl的图片转换为字节,这里要注意,要将图片的属性也写出来即D:/girl.jpg不能写成D:/girl

over 客户端就这样的over了,来我们接着说说服务器端,也就是接收端,同样接收端要是撇卡初始化的那点事儿,那么,也变得尤为的简洁了,也就是将接收到的数据还原为图片
当然,我这样说肯定很多人就默默的笑了,你不是废话的麽,肯定要还原的呀!!!哈哈   那就看看 如何还原的吧
//这里开辟了1M的字节空间 也就是一次图片的传输最大是1M大小
byte[] bytes = new byte[1024*1024];
int got = Soc_Temp.Receive(bytes);
// 将接受到的数据写入内存
MemoryStream fs = new MemoryStream();
fs.Write(bytes,0,got);
//使用Image类从内存中再次将数据读出来并保存为jpg图片
//注意 这里 无法保存在C盘
Image Img = Image.FromStream(fs);
Img.Save(desPathName,ImageFormat.Jpeg);
Debug.Log("保存完毕!!!");
//记得关闭流对象的哦
fs.Close();  
注意,这里使用Image类下的save方法,不能将数据保存在C盘,我之前就是在这里卡住了 哭,切记.切记
同样的,每个函数具体是神马意思,我就不展开阐述的了,翻阅MSDN你知道会比我这里讲述的更多....Everybody know that!!!!

OK,上边,上边只是讲了讲核心的部分,下边我将会将完整的代码贴出来,主要实现的一个功能是:客户端点击发送图片按钮,在服务器端的界面上就会显示该图片

那怎么做的呢?

我的做法是:将传输过来的图片保存在Asset下的Resources(没有的话自己创建一个)文件中,然后,使用Resources.Load方法动态的加载出来,当然,若有其他的途径欢迎拍砖,本人也是菜鸟一只,希望大家能多多的交流~嘎嘎..

下边就先贴出服务器端的代码 代码中也写好了注释,我这里是将套接字写在一个脚本中的,也因为服务器只有一个所以写的是一个单例类,接受数据是开启一个线程接受的

服务器 socket(套接字)脚本代码 服务器端的发送数据也写在其中的了,但, 我没有使用。注意这里需要引用的命名空间 特别注意的是如果 在写using System.Drawing提示找不

的时候,需要将System.Drawing.dll文件拷贝到当前工程中来

using UnityEngine;
using System.Collections;using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Drawing.Imaging;
using System.Drawing;
using System.Net;
using System.IO;
using System.Threading;//单例类
public class ser  {private static ser serInstance = null;private ser(){}public static ser GetInstance(){lock(lockHelper){if( serInstance == null ){serInstance = new ser();}return serInstance;}}private Socket Soc_Temp;private TcpListener tcpLister;private bool live = true;private bool abort_Start=false;private bool abort_Get=false;private bool abort_Send=false;public string send_Mes = "send_Mes";public string get_Mes = "get_Mes";Thread Thread_Start;Thread Thread_getData;Thread Thread_sendData;private static object lockHelper = new object();//图片保存的地址与名字private string desPathName = Application.dataPath + "/Resources/girl.jpg";public bool beSave = false;public void Server_Start(){begin();}void begin(){//把/转换为\ 这是因为 Image保存时的路径需要的是\//而Application.dataPath的路径中是/desPathName.Replace("/","\\");Debug.Log(desPathName);abort_Start = true;tcpLister = new TcpListener(IPAddress.Any,8080);tcpLister.Start();Thread_Start = new Thread(Start);Thread_Start.IsBackground = true;Thread_Start.Start();Debug.Log("线程开启状态Thread_Start="+Thread_Start.ThreadState);Debug.Log("线程开启状态Thread_Start="+Thread_Start.IsAlive);}//TCP连接  并且 开启一个函数线程专门用于接收数据void Start(){while(live){try{if(tcpLister.Pending()){abort_Get = true;Soc_Temp = tcpLister.AcceptSocket();Thread_getData = new Thread(getData);Thread_getData.IsBackground = true;Thread_getData.Start();Debug.Log("线程接收状态Thread_getData="+Thread_getData.ThreadState);Debug.Log("线程接收状态Thread_getData="+Thread_getData.IsAlive);}}catch(Exception e){Debug.Log(e.Data.ToString());Soc_Temp.Close();Soc_Temp = null;live = false;tcpLister.Stop();Thread_getData.Abort();}}}//接收数据线程函数void getData(){while(live){try{//避免在多线程下数据接收错误lock(lockHelper){//这里开辟了1M的字节空间 也就是一次图片的传输最大是1M大小byte[] bytes = new byte[1024*1024];int got = Soc_Temp.Receive(bytes);// 将接受到的数据写入内存MemoryStream fs = new MemoryStream();fs.Write(bytes,0,got);//从内存中再次将数据读出来并保存为jpg图片//注意 这里 无法保存在C盘Image Img = Image.FromStream(fs);Img.Save(desPathName,ImageFormat.Jpeg);Debug.Log("保存完毕!!!");beSave = true;fs.Close();}}catch(Exception e){Debug.Log(e.Data.ToString());live = false;Soc_Temp.Close();Soc_Temp = null;Thread_getData.Abort();}}}//发送数据 线程函数public void SendM(){abort_Send = true;Thread_sendData = new Thread(sendData);Thread_sendData.IsBackground = true;Thread_sendData.Start();Debug.Log("线程发送状态Thread_Start="+Thread_sendData.ThreadState);Debug.Log("线程发送状态Thread_Start="+Thread_sendData.IsAlive);}//发送数据void sendData(){try{byte[] send_bytes = Encoding.UTF8.GetBytes(send_Mes);Soc_Temp.Send(send_bytes);}catch(Exception e){Debug.Log(e.Data.ToString());live = false;Soc_Temp.Close();Soc_Temp = null;Thread_getData.Abort();}}//终止线程public void setAbort(){if( abort_Start ){Thread_Start.Abort();Debug.Log("开启状态Thread_Start="+Thread_Start.ThreadState);Debug.Log("开启状态Thread_Start="+Thread_Start.IsAlive);abort_Start = false;}if( abort_Get ){Thread_getData.Abort();Debug.Log("接受状态Thread_getData="+Thread_getData.ThreadState);Debug.Log("接受状态Thread_getData="+Thread_getData.IsAlive);abort_Get = false;}if( abort_Send ){Thread_sendData.Abort();Debug.Log("发送状态Thread_sendData="+Thread_sendData.ThreadState);Debug.Log("发送状态State:Thread_sendData="+Thread_sendData.IsAlive);abort_Send = false;}}}

下边贴出 真正做事的那个脚本,额,我该怎么表达呐,哎 怪我语文没学好,尴尬  

也就是这个脚本中的代码将会去调用上边的脚本,直接上代码,大家就会一目了然的了

using UnityEngine;
using System.Collections;using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Drawing.Imaging;
using System.Drawing;
using System.Net;
using System.IO;public class setServer : MonoBehaviour {ser m_ser;Texture2D m_Texure;void Start(){m_ser = ser.GetInstance();}void OnDestroy(){print(" 脚本以关闭");m_ser.setAbort();}void OnGUI(){//开启服务器if( GUI.Button(new Rect((Screen.width/2)-50,(Screen.height/2),100,30),"开启服务器") ){m_ser.Server_Start();}//图过图片已经传输过来并且保存在了指定的位置if( m_ser.beSave ){//Load方法加载Resource文件夹下的资源girl不用写成girl.jpgm_Texure = Resources.Load("girl") as Texture2D;if(m_Texure != null)	{GUI.DrawTexture(new Rect(0,0,m_Texure.width,m_Texure.height),m_Texure);}}}
}

可以看到,在这个脚本中,将传输过来的图片Load出来,然后使用GUI.DrawTexture方法贴出来


OK,OK,OK,服务器端就这么Over了,那么接着看看客户端的代码

using UnityEngine;
using System.Collections;using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.IO;public class client : MonoBehaviour {private Socket clientMsg;struct sendDate{public byte[] fssize;};private sendDate Msg;// Use this for initializationvoid Start (){IPEndPoint ipendpiont = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8080); clientMsg = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);clientMsg.Connect(ipendpiont);}void OnGUI(){if(GUI.Button(new Rect(Screen.width/2,0,100,50),"发送图片")){//声明一个文件流对象fs,并实例化该对象FileStream fs = new FileStream("D:/girl.jpg",FileMode.OpenOrCreate,FileAccess.Read);//为了防止socket连接出现异常,所以使用try...catch语句 try{//下边三行代码是 将fs对象所操作的图片转换为字节数据,并保存在Msg.fssize数组中Msg.fssize = new byte[fs.Length];BinaryReader strread = new BinaryReader(fs);strread.Read(Msg.fssize,0,Msg.fssize.Length);//发送数据clientMsg.Send(Msg.fssize);}catch(SocketException e){Debug.Log(e.Data.ToString());fs.Close();clientMsg.Shutdown(System.Net.Sockets.SocketShutdown.Send);clientMsg.Close();clientMsg = null;}}}void OnDestroy(){clientMsg.Close();}}

同样,代码还是比较简洁的,那么至此,整个过程就算是完成了,大家可以尝试一下

当然,这个只是传输图片的,也可以传输视频,音频等文件,虽然,我还没有去尝试,但是,一定是可以的,因为,我们所有的东西在电脑上都是以010101形式保存的,也就是二进制文件保存的,所以,一定是可以传输。微笑


最后上一张图片


欢迎大家拍砖,若发现错误,还望不忘拿起板砖,板砖,狠狠的拍向我。。。。。大笑


另外:若转载,请标明出处,文章写的也是蛮累人的~   谢谢大家....   

QQ:2306798290








http://www.ppmy.cn/news/366388.html

相关文章

html上传图片后,在页面显示上传的图片

第一种方法&#xff1a; 1.前端代码 <form class"container" enctype"multipart/form-data" method"post" idformBox name"form"> <input type"file" id"chooseImage" name"file"> <…

.NET Base64解码图片及上传

/// <summary>/// 图片上传 Base64解码/// </summary>/// <param name"dataURL">Base64数据</param>/// <param name"path">保存路径</param>/// <param name"imgName">图片名字</param>/// &l…

前端必备————图片转换成css或js方法

https://zhuanlan.zhihu.com/p/24551014?utm_sourcetuicool&utm_mediumreferral 作者&#xff1a;小爝 链接&#xff1a;https://zhuanlan.zhihu.com/p/24551014 来源&#xff1a;知乎 著作权归作者所有。商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。 今…

maya餐具图片_有哪些价格低但是逼格高很文艺又实用的物品呢?

信的恋人火漆印章(《穿越宇宙》宇航员版) “写信真是一件温柔的事&#xff0c;细腻的小心思就藏在横竖撇捺之中&#xff0c;像是一只害羞的小兽躲在情意绵绵的字里行间&#xff0c;被火漆封印起来&#xff0c;等着解封的那一刻窜出来&#xff0c;跳进启信人眼底的柔波里。” 送…

推荐一个美中不失优雅的博客网主页(素材参考---麋鹿鲁哟)

读者, 你好&#xff0c;这里是豪豪在线客服为你服务&#xff0c;接下来我将想你献上等你许久的专属于个人博客主页&#xff0c;等跟着我的步骤&#xff0c;相信可以在很短时间内&#xff0c;你也可以拥有专属于自己的博客主页面。在这之前&#xff0c;请在心中默念&#xff0c;…

springboot整合xxl-job

文章目录 前言一、xxl-job是什么&#xff1f;二、使用步骤1.下载源码,并部署好2.模仿xxl-job-executor-sample-springboot 自己建立一个服务1 引入xxl-job核心依赖2 创建服务,配置yml3 创建一个配置类,用于读取上述配置,并配置好handel信息4 创建一个执行器的任务类,用于执行真…

String在Java中真的是不可变吗

在Java中&#xff0c;String确实是不可变的。这意味着一旦创建了一个String对象&#xff0c;它的值就不能被修改。当你对一个String对象执行一些操作&#xff08;如拼接、替换等&#xff09;&#xff0c;实际上是创建了一个新的String对象&#xff0c;原始的String对象保持不变…

HAProxy概述、搭建Web群集

HAProxy概述、搭建Web群集 一、HAProxy概述1、HAProxy的主要特性2、常见的Web集群调度器3、Haproxy应用分析4、Haproxy调度算法原理 二、LVS、Nginx、HAproxy的区别三、LVS、Nginx、HAproxy的优缺点1、Nginx的优点&#xff1a;2、Nginx的缺点&#xff1a;3、LVS的优点&#xff…