Jtro的技术分享:游戏客户端与服务器(c#)通讯_同步Sock
在游戏界,独立游戏层出不穷,但是大部分都是单机,网络游戏很少,因为不会有独立开发者自己整一个服务器,除非你先去买个虚拟服务器。网络通讯一直是一个很大的学术,今天研究了一下,把服务器端的代码和unity作为客户端的代码写了下来。可能还不完善大家凑合看,有什么问题可以私我。给大家一个网络编程的思考。
废话不多说,直接上代码,首先是服务器端的,这个不需要打开unity,直接打开mono或者是vs直接输入代码在控制台运行就行,在这里,围栏方便大家调试我把源码贴出来。大家复制就行了。
```
/*
* 脚本功能:服务器
* 作者 :张曙光
* 日期 :2017.11.11
*/
using System;
using System.Net; //引入命名空间
using System.Net.Sockets; //引入命名空间
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Server
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("这是一个服务器,你相信吗?");
//Socket 套接字
Socket listenfd = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
/*
* 现在解释上面的一行代码,功能是实例了一个套接字,它的3个参数分别代表了地址簇、套接字类型和协议
* 地址簇指明用的是IPv4还是用的是IPv6,
* SocketType指的是套接字的类型,游戏开发中用的stream居多
* ProtocolType指明使用的协议,如你所见,用的是TCP协议
*/
//Bind
IPAddress ipAdr = IPAddress.Parse("127.0.0.1");
IPEndPoint ipEp = new IPEndPoint(ipAdr ,1234);
listenfd.Bind(ipEp);
/*
* listenfd.Bind(ipEp)将给listenfd套接字绑定IP和端口。在这里是绑定的是本地地址127.0.0.1和1234号端口
* 127.0.0.1是回送地址,指的是本地机,一般用来测试,当然你可以设置成另外一台机的ip地址,然后在2台电
* 脑上分别运行客户端和服务器端
*/
//Listen
listenfd.Listen(0);
Console.WriteLine("[ 服务器 ] 启动成功");
/*
* listenfd.Listen(0)开启监听器,等待客户端连接,参数backlog指定队列中最多可容纳多少人连接,0表示不限制
*/
while (true)
{
//Accept
Socket connfd = listenfd.Accept();
Console.WriteLine("[服务器] Accept");
/*
* 开启监听器后,服务器开始调用listenfd.Accept()接收客户端连接。本案例使用的所有Socket方法都是“阻塞”
* 方法,也就是说,如果一直没有客户点连接进来的话,服务器的程序会一直卡在listenfd.Accpect()处,不往
* 下执行,直到客户端连接之后Accpet返回一个新的客户端的Socket,对于服务器来说它有一个监听的Socket(案
* 例中的listenfd)用来接收Accpet客户端的连接,对于每一个客户端来说,还有一个专门的Socket(案例中的Connfd)
* 用来处理该客户端的数据
*/
//Recv
byte[] readBuff = new byte[1024];
int count = connfd.Receive(readBuff);
string str = System.Text.Encoding.UTF8.GetString(readBuff, 0, count);
Console.WriteLine("[ 服务器接收 ]" +str);
/*
* 服务器通过connfd.Receive接收客户端数据,receive也是阻塞的方法,没有接收到客户端数据时,程序卡在Receive
* 处,不会向下执行,Receive带有一个byte[]类型的参数,它将储存接收到的数据,Receive的返回值则指明接收到的
* 数据长度之后,用string str = System.Text.Encoding.UTF8.GetString(readBuff, 0, count);这段代码将byte[]数
* 组转化为字符串显示在屏幕上
*/
//Send
byte[] bytes = System.Text.Encoding.Default.GetBytes(" Serv echo " + str);
connfd.Send(bytes);
/*
* 服务器通过Connfd.Send发送数据,它接收一个byte[]类型的参数指明要发送的内容,Send的返回值指明发送的数据长
* 度(案例中没有),服务器程序用System.Text.Encoding.Default.GetBytes(" Serv echo " + str)把字符串转换成
* byte[]数组,然后发送给客户端。
*/
}
}
}
}
```
注释已经写的很明白了。
这是运行的图:
服务器运行的 时候 客户端还没链接那么接下来就是unity客户端的了
首先新建一个unity空工程,我的unity版本是2017.2.0.f3的版本,所以2017.2.0.f3版本之下的版本复制粘贴都没问题。
新建画布添加组件,和我这个差不多就行。排版自己排就行。
组件 H ierarchy 视图 Game 视图新建一个脚本,叫NET,这里同样贴出代码,方便大家复制粘贴调试。
```
//初创日期 :2017.11.11
//脚本功能 :客户端
//脚本挂载在: 不需要挂在任何物体上
//作者: Jtro//第一次修改:
/**/
using System.Collections;
using System.Collections.Generic;using UnityEngine;using System.Net; //引入命名空间
using System.Net.Sockets; //引入命名空间
using UnityEngine.UI;public class net : MonoBehaviour { Socket socket; //与服务器端的套接字
public InputField HostInput; //服务器端的ip地址
public InputField PortInput; //服务器端的端口,其实在服务器那块7777端口也能用。
public Text RecvText; //服务器收到的信息
public Text ClientText; //客户端的信息
const int BUFFER_SIZE = 1024; //接收缓冲区
byte[] readBuff = new byte[BUFFER_SIZE];
////// 按钮点击事件
///public void Btn_Connetion()
{ //Socket
socket = new Socket(AddressFamily .InterNetwork,SocketType.Stream ,ProtocolType.Tcp);
//Connect
string host = HostInput.text; string strport = PortInput.text; int port = int .Parse(strport); socket.Connect(host ,port); ClientText.text = "客户端地址 " + socket.LocalEndPoint.ToString();
//Send
string str = "HELLO , I am Jtro.";
string time = System.DateTime.Now.ToString();
byte[] bytes = System.Text.Encoding.Default.GetBytes(str+ " "+time);
socket.Send(bytes);
//Recv
int count = socket.Receive(readBuff);
str = System.Text.Encoding.UTF8.GetString(readBuff, 0, count);
RecvText.text = str; //Close socket.Close(); }
// Use this for initialization
void Start () {}
// Update is called once per framevoid Update () {
}
}
```
然后运行时的截图
输入 服务器地址 点击连接服务器好了这样就行了,可以看到发送的信息,那么,如果是要写一个及时聊天系统该如何写呢?
下次把这个功能实现
OK,感谢简书,感谢读完的你。
然后现在的简书MARKDOEN不能发图片了吗,以前是可以的,现在这个这是用富文本写的,所以代码没有被排版,有谁知道Markdown现在怎么发图片请告诉我一下。谢啦