《丛林战争》是一款完整的网络游戏案例,运用U3D开发客户端,Socket开发服务端,其中涉及到了网络编程、数据库和Unity的功能实现,之前通过U3D开发了一个单机游戏《黑暗之光》,并没有涉及网络编程的知识,通过《丛林战争》这个完整的游戏,系统性地学习网络编程,并进一步学习利用U3D开发游戏。

本篇内容是网络编程的基础知识,主要内容如下:

  • 介绍TCP/IP的基本概念以及基础TCP协议
  • 实现服务器端与客户端的同步收发
  • 实现服务器端与客户端的异步收发

1. TCP/IP基本概念

下图是一个网络的简化图,可以看出IP的作用是在复杂的网络环境中将数据包发给最终的目标地址,本节主要介绍IP、端口号和TCP协议。

1.1 IP

IP分为局域网IP和公网IP,每台机都有这两个IP。当一个路由器连接多个主机,相当于路由器与这些主机组成了一个局域网,路由器会给每个主机分配一个局域网IP,可以在Win+R > cmd,小黑窗中输入ipconfig查到,公网IP则可以通过百度查询到。

1.2 端口号

主机之间通过路由器进行通信,以主机B与主机D通信为例,B通过ip地址找到了主机D,连接建立之后,考虑到进行通信最终是软件之间的交互,因此需要搞清是与什么软件进行通信。假设D中有QQ、微信、绝地求生等软件,需要为每个软件分配一个端口号。(即ip找机器,端口号找软件)

下图就是一个例子,IP数据172.23.12.14找到了主机A,A中各个端口号对应不同应用(图中以服务端为例),需要通过独有的端口号找到对应软件。后期也会学习如何向系统申请端口号。

一般知名端口号在0~1023之间,而我们经常使用的自定义/动态分配的端口号则一般在1024~65535之间。详细参考百度百科。https://baike.baidu.com/item/%E7%AB%AF%E5%8F%A3%E5%8F%B7/10883658

1.3 TCP协议(三次握手与四次挥手)

三次握手与四次挥手的详解可以参照该博客:https://blog.csdn.net/sssnmnmjmf/article/details/68486261

在这里大致解释一下:(主机A代表张三,B代表李四)

三次握手:

张三:李四你在吗?(请求连接)

李四:张三我在的(确认应答)

张三:好的我要发数据了(对李四的确认应答)

四次挥手:

张三:李四我没事了,挂电话了(请求切断)

李四:好的,知道你没事了(确认应答)

李四:那就这样,挂电话吧(请求切断)

张三:那我挂了(确认应答)

2 利用TCP协议实现服务端与客户端的通信

利用C#服务器控制应用程序实现简单的通信,步骤如下图,图中所示即为服务端与客户端的连接步骤,TCP连接都是基于这个规则。

2.1 服务端与客户端的同步收发

服务端代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
namespace TCPServer
{class Program{static void Main(string[] args){Socket socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);  //第一个参数表示时候用ipv4,第二个Stream表示TCP传输用到的数据流,如果是UDP协议可以用Dgram报文//IPAddress xxx.xx.xx.xx IPEndPoint xxx.xx.xx.x:port 需要用到using System.Net;IPAddress ipAddr = IPAddress.Parse("127.0.0.1");    //服务器端申请ip及端口号IPEndPoint ipEndPoint = new IPEndPoint(ipAddr, 1200);socketServer.Bind(ipEndPoint);  //进行绑定socketServer.Listen(10);    //最多处理10个连接的队列Socket socketClient = socketServer.Accept();  // 接收客户端连接,之后通过socketClient进行对客户端数据的收发//发送给客户端string sendMsg = "hello,客户端";byte[] sendData = Encoding.UTF8.GetBytes(sendMsg);  //字符串转为bype数组发送,用到using System.Text;socketClient.Send(sendData);//从客户端接收byte[] recvData = new byte[1024];   //分配1024字节大小的空间存储int count = socketClient.Receive(recvData); //接收到的字节大小string recvMsg = Encoding.UTF8.GetString(recvData, 0, count);  //数组转为字符串,转换0~count长度,由于recvData未填满,直接转换recvData会出错Console.WriteLine(recvMsg);socketClient.Close();socketServer.Close();}}
}

客户端代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
namespace TCPClient
{class Program{static void Main(string[] args){Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);clientSocket.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1200));//从服务端接收数据byte[] dataRecv = new byte[1024];   int count = clientSocket.Receive(dataRecv);string msgRecv = Encoding.UTF8.GetString(dataRecv, 0, count);Console.WriteLine(msgRecv);//向服务端发送数据string msgSend = Console.ReadLine();byte[] dataSend = Encoding.UTF8.GetBytes(msgSend);  //字符串转为bype数组发送,用到using System.Text;clientSocket.Send(dataSend);Console.ReadKey();clientSocket.Close();}}
}

结果如下。

上述方法是一个同步发送与接收的例子,当服务器处于接收状态时,无法发送数据给客户端,反之亦然。因此需要一种异步的处理方法。

2.2 服务端实现异步接收

在服务器端添加异步接收功能,将之前的代码修改为:

static byte[] dataBuffer = new byte[1024];static void StartAsync(){Socket socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);  //第一个参数表示时候用ipv4,第二个Stream表示TCP传输用到的数据流,如果是UDP协议可以用Dgram报文//IPAddress xxx.xx.xx.xx IPEndPoint xxx.xx.xx.x:port 需要用到using System.Net;IPAddress ipAddr = IPAddress.Parse("127.0.0.1");    //服务器端申请ip及端口号IPEndPoint ipEndPoint = new IPEndPoint(ipAddr, 1200);socketServer.Bind(ipEndPoint);  //进行绑定socketServer.Listen(10);    //最多处理10个连接的队列Socket socketClient = socketServer.Accept();  // 接收客户端连接,之后通过socketClient进行对客户端数据的收发//发送给客户端string sendMsg = "hello,客户端";byte[] sendData = Encoding.UTF8.GetBytes(sendMsg);  //字符串转为bype数组发送,用到using System.Text;socketClient.Send(sendData);//从客户端接收socketClient.BeginReceive(dataBuffer, 0, 1024, SocketFlags.None, ReceiveCallBack, socketClient);   //开始监听客户端数据,当接收到数据时调用RecvCallBack,实现异步接收Console.ReadKey();socketClient.Close();socketServer.Close();}static void ReceiveCallBack(IAsyncResult ar){Socket clientSocket = ar.AsyncState as Socket;int count = clientSocket.EndReceive(ar);string msg = Encoding.UTF8.GetString(dataBuffer, 0, count);Console.WriteLine("接收到的消息为:" + msg);clientSocket.BeginReceive(dataBuffer, 0, 1024, SocketFlags.None, ReceiveCallBack, clientSocket);    //接收完一条消息后回掉自身,继续接收}

在客户端发送数据代码前加一个while(true)以达到不断发送数据的目的,结果如下。

2.3 服务端接收多个客户端的异步数据

若要使服务端同时接收多个客户端的数据,服务端实现异步收发需要调用AcceptCallBack

socketServer.BeginAccept(AcceptCallBack, socketServer);  

服务端代码如下

     static void StartAsyncAcceptAndRecv(){Socket socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);  //第一个参数表示时候用ipv4,第二个Stream表示TCP传输用到的数据流,如果是UDP协议可以用Dgram报文IPAddress ipAddr = IPAddress.Parse("127.0.0.1");    //服务器端申请ip及端口号IPEndPoint ipEndPoint = new IPEndPoint(ipAddr, 1200);socketServer.Bind(ipEndPoint);  //进行绑定socketServer.Listen(10);    //最多处理10个连接的队列//Socket socketClient = socketServer.Accept();  // 接收客户端连接,之后通过socketClient进行对客户端数据的收发socketServer.BeginAccept(AcceptCallBack, socketServer);}

客户端不变,此时服务端可以接收多个客户端的数据,如下图所示。

工程源码下载地址:https://download.csdn.net/download/s1314_jhc/10519603(下载分不够可以私聊我发代码)

网络游戏《丛林战争》开发与学习之(一):网络编程的基础知识相关推荐

  1. Java编程语言学习:Java语言编程的基础知识之Java的变量与数据类型、符号、运算符、数组Array总结之详细攻略

    Java编程语言学习:Java语言编程的基础知识之Java的变量与数据类型.符号.运算符.数组Array总结之详细攻略 目录 Java语言编程的基础知识之Java的变量与数据类型.符号.运算符.数组总 ...

  2. 黑马程序员_java自学学习笔记(八)----网络编程

    黑马程序员_java自学学习笔记(八)----网络编程 android培训. java培训.期待与您交流! 网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很长一段时间无 ...

  3. react ui框架_Web开发 React 学习(二十)连载基础篇大结局

    系列文章: 测开技能--Web开发 React 学习(一) 测开技能--Web开发 React 学习(二)环境搭建 测开技能--Web开发 React 学习(三)元素的渲染 测开技能--Web开发 R ...

  4. 学习笔记:Java 并发编程①_基础知识入门

    若文章内容或图片失效,请留言反馈. 部分素材来自网络,若不小心影响到您的利益,请联系博主删除. 视频链接:https://www.bilibili.com/video/av81461839 视频下载: ...

  5. 学习Spring必学的Java基础知识

    学习Spring必学的Java基础知识(1)----反射 引述要学习Spring框架的技术内幕,必须事先掌握一些基本的Java知识,正所谓"登高必自卑,涉远必自迩".以下几项Jav ...

  6. pwn学习总结(四)—— 堆基础知识(持续更新)

    pwn学习总结(四)-- 堆基础知识(持续更新) 前言 chunk 使用中(分配后) 空闲中(释放后) 堆块大小 空间复用 bins fastbin unsorted bin small bin 前言 ...

  7. 3D视觉学习计划之PCL库的基础知识

    3D视觉学习计划之PCL库的基础知识 一.PCL库的概述 PCL是一个大型跨平台开源C++编程库,它在吸收了前人点云相关研究基础上建立起来,实现了大量点云相关的通用算法和高效数据结构,涉及到点云获取. ...

  8. 从零开始学习VIO笔记 --- 第一讲:基础知识(四元数,李代数)

    从零开始学习VIO笔记 --- 第一讲:基础知识(四元数,李代数) 一. 向量的内积与外积 二. 旋转与平移 2.1 旋转表示 --- 旋转矩阵R 2.2 平移向量 2.3 变换矩阵T与齐次坐标 2. ...

  9. Kotlin学习(一):Kotlin基础知识

    Kotlin学习(一):Kotlin基础知识 定义变量常量 在Kotlin中,定义变量时有以下几点与java不同: 位置不同:在 Kotlin 中,数据类型要放到变量后面,并且用冒号(:)分隔,这正好 ...

最新文章

  1. 使用python爬取教程生成PDF
  2. php发送指令,PHP发送AT指令实例代码
  3. linux 关闭磁盘检测,linux下检测磁盘状态
  4. Java开发知识之Java中的集合上List接口以及子类讲解.
  5. 安装kinetic之后无法import cv2解决方案
  6. php签名墙,肺功能检查质量控制网
  7. HTML5与原生APP之争胜负已出?
  8. js与php时间戳,js时间戳与日期格式之间的互转
  9. 网页从数据库读取出现乱码问题
  10. 台式计算机能装蓝牙吗,台式机如何安装蓝牙
  11. 运维是技术含量最低的岗位吗?自学应该看书还是看视频?答案都在这里!
  12. Kyan网络监控设备账号密码泄露漏洞
  13. excel自动筛选_在Excel 2007中按选择自动筛选
  14. 2017下半年掘金日报优质文章合集:Android篇,android开发工程师
  15. 数据结构顺序表和单链表优缺点
  16. 使用http-server启本地服务
  17. 【学习笔记】斗鱼p2p架构
  18. dnspod 动态域名的使用。openwrt使用dnspod动态域名解析。
  19. 用 TimingLaba(时方校园定时广播系统)软件,实现学校、办公室定时播放体操、上下课(班)铃声、休息音乐
  20. Latex之给字符上加横线、波浪线、^等

热门文章

  1. android开发之音频拼接
  2. MyBatis-Plus 从入门到上手-进阶版
  3. MAC上配置搭配CH340/CH341 USB转串口芯片的Arduino
  4. python开发桌面应用怎么样_python为什么不适合开发桌面软件?
  5. DRGs系统的研究与应用-北京项目组开发
  6. 【Linux系列-2】iostat命令详解
  7. 2022年湖北初级职称(助理工程师)评定条件及评定流程是什么呢?
  8. 数据库管理系统实现技术
  9. 信天创投蒋宇捷:我对区块链行业的12点观察与思考
  10. 情绪调节的自适应_自我调节情绪的八种好办法