小白初识Unity Socket编程,对一些疑惑代码的测试。

小白初识Unity Socket编程,对一些疑惑代码的测试。

学习中我坚信要知其然,也要知其所以然,不能只当API的搬运工。

根据Unity3d 网络游戏实战(第二版)一边看,一边自己研究写写想法。

目前只看到了,第一章,第二章,讲的也就是基础Socket的简单语法,双端代码。
基本知识书上讲过的不谈,主要是自己看书的时候会有一些想法,想知道为什么这么写?如果不这么写会发生什么事情。

就目前我对于Socket的理解,客户端步骤:
单线程情况下,客户端创建链接:

public void Connetion()
{
	//Socket
	socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp);
	//Connect
	socket.Connect("192.168.1.0", 8888);
}

这里没啥问题
然后发送数据给服务端

	public void Send()
	{
		//Send
		string sendStr = InputFeld.text;
		byte[] sendBytes = System.Text.Encoding.Default.GetBytes(sendStr);
		socket.Send(sendBytes);
        //Recv
        byte[] readBuff = new byte[1024];
        int count = socket.Receive(readBuff);
        string recvStr = System.Text.Encoding.UTF8.GetString(readBuff, 0, count);
        text.text = recvStr;
        //Close
        socket.Close();
	}

第一个问题 连接上之手Receive,Close是不是必须的?

这里我的问题就来了,是不是一定要Receive和Close 如果我屏蔽了这两段代码会发生什么事情?
对此我进行了实验。
首先屏蔽了Receive这段,然后服务端的代码如下

public static void Main(string[] args)
        {
            Socket lisnter = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPAddress iPAddress = IPAddress.Parse("192.168.1.0");
            IPEndPoint iPEndPoint = new IPEndPoint(iPAddress, 8888);
            lisnter.Bind(iPEndPoint);
            lisnter.Listen(0);
            Console.WriteLine("小小故事汇的服务器启动");
            while (true)
            {
                Socket connfd = lisnter.Accept();
                Console.WriteLine("有客户端连接");
                byte[] readBuff = new byte[8];
                int count = connfd.Receive(readBuff);
                string readStr = System.Text.Encoding.Default.GetString(readBuff, 0, count);
                Console.WriteLine("服务器接收:" + readStr);
                byte[] sendByte = System.Text.Encoding.Default.GetBytes(System.DateTime.Now.ToString());
                Console.WriteLine("服务器发送");
            }
        }

屏蔽Receive代码后发现没啥问题,只是客户端收不到罢了。

然后我测试了Close还是没啥问题,算了先不管这个Close了。

结论:Receive与Close并不是必须的只是收不到东西罢了。

第二个问题 客户端发服务端不收客户端会卡死,那么反过来呢?

然后继续看书,发现书上写如果客户端不断发送数据给服务端,当超过缓存上限客户端就会卡死,我作死尝试了下果然,然后我想既然客户端会卡死,那我服务端发,客户端收呢?然后我试验了下。

public static void Main(string[] args)
        {
            Socket lisnter = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPAddress iPAddress = IPAddress.Parse("192.168.232.1");
            IPEndPoint iPEndPoint = new IPEndPoint(iPAddress, 8888);
            lisnter.Bind(iPEndPoint);
            lisnter.Listen(0);
            Console.WriteLine("小小故事汇的服务器启动");
            while (true)
            {
                Socket connfd = lisnter.Accept();
                Console.WriteLine("有客户端连接");
                byte[] readBuff = new byte[8];
                int count = connfd.Receive(readBuff);
                string readStr = System.Text.Encoding.Default.GetString(readBuff, 0, count);
                Console.WriteLine("服务器接收:" + readStr);
                for (int i = 0; i < 2; i++)
                {
                    byte[] sendByte = System.Text.Encoding.Default.GetBytes(System.DateTime.Now.ToString()+"\n\r");
                    Console.WriteLine("服务器发送:" + i);
                    connfd.Send(sendByte);
                }
                /*byte[] sendByte = System.Text.Encoding.Default.GetBytes(System.DateTime.Now.ToString());
                Console.WriteLine("服务器发送");*/
            }
        }

客户端那里对Receive代码进行屏蔽后,有趣的事情来了~
服务端他报错了,表示客户端已经断开了链接,我看了一眼服务端代码 i = 1,也就是说第一个发出去了不管客户端收没收到,服务端第二个要发的时候已经找不到地方发了。
那么我们就把Close也关了。
OK程序顺利运行了。在这里插入图片描述
那我们加大力度再来试试 这次1W结果和奇怪服务端没有卡死
在这里插入图片描述
虽然没有卡死但我也不知道他发到哪里去了这里也是希望能有大佬告诉我一下了。

然后我想那我们收一收试试看,然后我把Receive开了出来。

发现收到的只有一点点,这里我觉得没啥问题,那就开个携程过个5秒再收,然后成功全部收到了。

结论:服务端发客户端不收服务端不会卡死,但为什么就不得而知了,可能是代码问题但也没就继续往下测试了。如果服务端发了很多可以存着等一会一起收。

第三个问题 接收时到底发生了什么事情?

在后面我巩固练习的时候发现了一个有意思的事情先看代码

 byte[] readBuff = new byte[512];
int count = connfd.Receive(readBuff);
string readStr = System.Text.Encoding.Default.GetString(readBuff, 0, count);
Console.WriteLine("服务器接收:" + readStr);

这是服务端的接收代码 我发现这个叫readBuff的东西并没有对他赋值仅仅只是new了一个出来,而后续代码也只是把他当作参数扔了进去就能知道收到了的数据,我觉得很有意思,迅速打了断点来了解在这里插入图片描述
当我按下连接服务器的按钮,我发现他在这里就停了下来,然后在int count = connfd.Receive(readBuff)断点就不见了,结合书上的之后我思考了下嗯这里因为单线程直到收到消息才会继续往下走,那么我来试试,按下发送按钮后,果然数据从null变成了有,也就是说数据是客户端那里发送出去后内部执行了一些操作赋予上去的。
这一段虽然说可能看上去研究有点蠢,但我还是觉得挺好玩的。
因为一般来说这个readBuff不应该=XXXXX么?怎么啥都没干就能收到数据了?

结论:readBuff会在客户端发送数据时自动赋值上去,与一般的赋值操作 readBuff = 某个 API 或 值 的思维并不一样。

第四个问题 多客户端下的情况

在我玩耍的时候,我又想到了一个有意思的玩法,就是我如果狂点连接会发生什么情况,我又作死了下,果然我的服务端爆炸了。
我开始思考了为啥会炸?这时候我想到了之前的Close代码。
我发现Close是放在发送那里的。那么我把它拿到前面来试试?
果然服务器不会炸了!那么就是说,close是为了和服务器断开链接然后把位置让出来给其他的客户端用。

结论:Close是为了断开链接给其他人用,如果同时又多个客户端练上去,服务端会炸。

第五个问题 Byte

 byte[] readBuff = new byte[512];

这是最简单也是最好测的代码了,只是因为书上当时填的512也没写是不是一定只能这个大小我进行了测试,先改成了1024 没问题。
改成2048呢?还是没问题。
那么小一点吧8,还是没问题?
可能和客户端有关 我尝试多发送一点输入了好多,咦只输出了8个数字,后面的被抛弃了,那么我就懂了原来如此。

结论:Byte决定了接收数据的大小

第六个问题 异步代码中的委托,自己调用自己?

这一块也研究了很久,同步异步的区别主要体现在同步代码一行,异步代码变成了两行 Begin ,end

	public void ReceiveCallback(IAsyncResult ar){
		try {
			Socket socket = (Socket) ar.AsyncState;
			int count = socket.EndReceive(ar);
			string s = System.Text.Encoding.UTF8.GetString(readBuff, 0, count);
			recvStr = s + "\n" + recvStr;
			socket.BeginReceive( readBuff, 0, 1024, 0,ReceiveCallback, socket);
		}
		catch (SocketException ex){
			Debug.Log("Socket Receive fail" + ex.ToString());
		}
	}

主要是这一行socket.BeginReceive( readBuff, 0, 1024, 0,ReceiveCallback, socket);我很奇怪为什么收完了还要调用一下自己?
然后结合书上说的可以不断接收消息我进行了测试,发现以前我只能收一次消息就停了,要再手动操作一下才能接收下一个,而现在我能不断接收消息,只要服务器那里不停我就能不停!简直太有意思~
也是通过这个示例我可以很好的就能理解异步代码的实现begin的委托接end,end的委托接下一个阶段要做的事情。

结论:异步代码可以更好的管理服务端与客户端,避免卡死,委托的存在也能更加简单方便的进行后续操作,而不需要人为手动去刷新接收消息或是其他操作。

好了到这里今天的学习也就结束了,我要继续看书了,因为异步和同步代码区别不是太大,主要也就是针对了,几个代码为什么存在,到底怎么回事,以及是否为必要代码测试了下。
下一章如果对多客户端又疑惑的话我会继续进行测试并发布测试结果与大家分享。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值