C# socket通信只能传输的字节流,所以 我们若是想利用socket传输任何东西,都必须将之以字节的形式进行传输
So 本文就抛砖引玉一下,以传输图片的形式来示范一下,socket传输除文本数据以外的数据 嘻嘻~~~
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行代码做了这么几件事情:
//这里开辟了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盘,我之前就是在这里卡住了 ,切记.切记
那怎么做的呢?
我的做法是:将传输过来的图片保存在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.jpg
m_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 initialization
void 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形式保存的,也就是二进制文件保存的,所以,一定是可以传输。
欢迎大家拍砖,若发现错误,还望不忘拿起板砖,板砖,狠狠的拍向我。。。。。
另外:若转载,请标明出处,文章写的也是蛮累人的~ 谢谢大家....