上一篇博客主要介绍了使用socket搭建服务端和客户端程序,这一篇来说说socket的数据传输,我们使用socket的目的是解决点对点之间的数据传输,之前提到了socket中一个重要的概念:端口。而socket传输数据的方式就是端口与端口之间以流(stream)的方式传输数据,socket命名空间中提供了该流的一个功能类(NetworkStream),用起来很方便,因为任何可以转换为二进制的数据都可以保存到流中,所以可以再客户端与服务器之前传输任何形式的数据。
下面我们介绍最基本的数据传输,由客户端向服务端发送数据,服务端接收到数据后并显示!还是按照惯例,服务端使用VS的控制台应用程序,客户端使用Unity3D来整。核心语句都有注释,重载方法可以再msdn上自行查看。如有错误,欢迎指正!
1、服务端接收数据并显示:
-
static void Main(string[] args)
-
{
-
const int bufferSize = 8792;//缓存大小,8192字节
-
IPAddress ip = IPAddress.Parse("192.168.0.13");
-
TcpListener tlistener = new TcpListener(ip, 10001);
-
tlistener.Start();
-
Console.WriteLine("服务器监听启动......");
-
TcpClient remoteClient = tlistener.AcceptTcpClient();//接收已连接的客户端,阻塞方法
-
Console.WriteLine("客户端已连接!local:{0}<---Client:{1}", remoteClient.Client.LocalEndPoint, remoteClient.Client.RemoteEndPoint);
-
//接收客户端发送的数据部分
-
NetworkStream streamToClient = remoteClient.GetStream();//获得来自客户端的流
-
byte[] buffer = new byte[bufferSize];//定义一个缓存buffer数组
-
int byteRead = streamToClient.Read(buffer,0,bufferSize);//将数据搞入缓存中(有朋友说read是阻塞方法,测试中未发现程序阻塞)
-
string msg = Encoding.Unicode.GetString(buffer, 0, byteRead);//从二进制转换为字符串对应的客户端会有从字符串转换为二进制的方法
-
Console.WriteLine("接收数据:{0}[{1}byte]",msg,byteRead);
-
ConsoleKey key;
-
do
-
{
-
key = Console.ReadKey(true).Key;
-
}
-
while (key != ConsoleKey.Q);
-
}
2、客户端封装字符串并发送:
-
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);
-
//客户端发送数据部分
-
string msg = "hello server";
-
NetworkStream streamToServer = client.GetStream();//获得客户端的流
-
byte[] buffer = Encoding.Unicode.GetBytes(msg);//将字符串转化为二进制
-
streamToServer.Write(buffer, 0, buffer.Length);//将转换好的二进制数据写入流中并发送
-
Debug.Log("发出消息:"+msg);
-
}
注意:以上只是基础的数据通信,真正项目中会存在两个问题:
1、数据量过大超过自定义的缓存大小,8192字节。一般发送字符串的话几乎不可能超过8192字节,如果发送图片或者音效的话就会出现数据被截断的现象。
2、以上程序只是一个程序想服务端发送一次数据的过程,不能多次发送,更不能多个客户端想服务器发送数据。
我上网查了下这两个问题,都应相应的解决方法,采用“分次读取,然后转存”的方式解决数据量过大,使用do/while双层嵌套可以解决多个客户端向服务器发送多个消息的问题,后续会将方案再分享给大家,与大家一起学习进步!