近些年webGame非常火爆,可惜相关教程实在少之又少,在我学习过程中无数次baidu,google。发现实际涉及wenGame核心的东西基本没有。于是就有了把我学习过程中使用和总结的代码拿上来给大家分享,让有共同爱好的同学们少走弯路。 本教程基于flex与c#,做到完全同步的游戏设计与编写。本教程只提供实现基本功能的代码,只要融会贯通,就能在此基础上制作出无比强大的网络游戏。 这篇教程最好是对c#有一定基础,会使用vs的同学。如果不会,我推荐看一下c#方面的书。 本教如需转载,请注名作者——汪舰,联系方式sxnrt#126.com。
这节讲讲如何用flex与c#进行socket通讯。 Flex端(当然你也完全可以用flash来写)使用import flash.net.Socket;包来做。通过ProgressEvent.SOCKET_DATA时刻检听是否接收到数据,接收到数据后触发函数receiveData。 使用var message:String=CurSocket.readMultiByte(CurSocket.bytesAvailable,"GB2312");可以把c#服务器发送过来的数据接收到。 CurSocket.writeUTF(Message.text);可以将数据发送给指定c#服务器 至于服务器端,只需要将第一节讲的代码稍加修改就可以使用。 需要注意的是这里要声明一个User类,其实本例中不使用类,直接在代码里声明TcpClient client也是可以的,做类的原因是在以后做游戏的时候,要给每一个连接进来的客户附加一些其他信息,比如用户名,血量,速度之类的,所以这里就先做成类的模式。 C#的代码很简单,等待连接,有客户连接后,把客户对象转换成自定义类User并保存到一个数组中。 当任何客户发送消息后,用循环向所有数组中的用户发送消息即可。下面请看代码。
Flex代码:C#代码- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Data;
- using System.Drawing;
- using System.Linq;
- using System.Text;
- using System.Windows.Forms;
- using System.Net;
- using System.Net.Sockets;
- using System.Threading;
- using System.IO;
- namespace flexSocketWinFrom
- {
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- IPAddress localAddress;
- private const int port = 8888;
- private TcpListener myListener;
- private List<TcpClient> userList = new List<TcpClient>();
- public BinaryReader br;
- private BinaryWriter bw;
- private void Form1_Load(object sender, EventArgs e)
- {
- //IPAddress[] addrIP = Dns.GetHostAddresses(Dns.GetHostName());
- //localAddress = addrIP[0];
- localAddress = IPAddress.Parse("192.168.1.100");
- }
- private void button1_Click(object sender, EventArgs e)
- {
- myListener = new TcpListener(localAddress, port);
- myListener.Start();
- textBox1.Text = string.Format("开始在{0}:{1}监听客户连接", localAddress, port);
- //创建一个线程监听客户端连接请求
- Thread myThread = new Thread(ListenClientConnect);
- myThread.Start();
- }
- private void ListenClientConnect()
- {
- TcpClient newClient = null;
- while (true)
- {
- try
- {
- newClient = myListener.AcceptTcpClient();//当有客户连接时执行一次下面的步骤
- }
- catch
- {
- //当单击“停止监听”或者退出此窗体时AcceptTcpClient()会产生异常
- //因此可以利用此异常退出循环
- break;
- }
- //每接受一个客户端连接,就创建一个对应的线程循环接收该客户端发来的信息
- User user = new User(newClient);
- Thread threadReceive = new Thread(ReceiveData);
- threadReceive.Start(user);
- userList.Add(newClient);//这个列表保存了所有连接中的用户
- textShow(string.Format("[{0}]进入", newClient.Client.RemoteEndPoint));
- textShow(string.Format("当前连接用户数:{0}", userList.Count));
- }
- }
- //现成援引From控件
- delegate void SetTextCallback(string text);
- private void textShow(string str)
- {
- if (textBox1.InvokeRequired)
- {
- SetTextCallback d = textShow;
- textBox1.Invoke(d, str);
- }
- else
- {
- this.textBox1.Text = "\n" + textBox1.Text + str;
- }
- }
- private void ReceiveData(object userState)
- {
- User user = (User)userState;
- TcpClient client = user.client;
- while (true)
- {
- string receiveString = null;
- try
- {
- textShow(string.Format("#接收前#"));
- //这里会阻塞,直到接收到客户端消息。值得注意的是这里每一个user都是独立的(应该是因为在类中创建client的原因),之前连接的所有客用端都会被监听,而不会被覆盖
- //如果直接在这创建client,则后面连接的client会覆盖掉前面连接的client,导致最后最后一个终端可以发消息
- receiveString = user.br.ReadString();
- textShow(string.Format("#接收后#"));
- }
- catch
- {
- break;
- }
- textShow(string.Format("[{0}]被输出;", receiveString));
-
- // bw.Write(System.Text.Encoding.GetEncoding("gb2312").GetBytes(receiveString));
- // bw.Flush();
- //如果想给所有客用端发信息,在开始时应该把客用端保存在一个array里,然后这里用循环发送
- SendToAllClient(client, receiveString);
- }
- }
- /// <summary>发送信息给所有客户</summary>
- /// <param name="user">指定发给哪个用户</param>
- /// <param name="message">信息内容</param>
- private void SendToAllClient(TcpClient ClientUser, string message)
- {
- for (int i = 0; i < userList.Count; i++)
- {
- TcpClient client = (TcpClient)userList[i];
- NetworkStream networkStream = client.GetStream();
- //将网络流作为二进制读写对象
- br = new BinaryReader(networkStream);
- bw = new BinaryWriter(networkStream);
- bw.Write(System.Text.Encoding.GetEncoding("gb2312").GetBytes(message));
- bw.Flush();
- }
- }
- }
- }
复制代码- User.cs类
- using System.Net.Sockets;
- using System.IO;
- namespace flexSocketWinFrom
- {
- class User
- {
- public TcpClient client { get; private set; }
- public BinaryReader br { get; private set; }
- public BinaryWriter bw { get; private set; }
- public string userName { get; set; }
- public User(TcpClient client)
- {
- this.client = client;
- NetworkStream networkStream = client.GetStream();
- br = new BinaryReader(networkStream);
- bw = new BinaryWriter(networkStream);
- }
- public void Close()
- {
- br.Close();
- bw.Close();
- client.Close();
- }
- }
- }
复制代码 本例中的重点就是通过代码readMultiByte可以从flex或flash向服务器发送socket消息。你打开2个页面就可以测试了,本例未解决的两个问题是一、客用关掉flex页面,服务器是不知道的。Flex本身也没有吸构函数,在后面的教程中将会讲解如何用心跳测试法及时获得离开用户。二、本例在本机运行是没有问题的,但是放到iis或者tomcat下会有安全权限错误,就是沙箱限制,这个显示网上都是写通过设置策略文件xml解决,其实不然,socket的沙箱限制和http的是不一样。这2个问题在以后的教程中将会解答。 下一节开始讲如何使用flex+socket制作一个真正的互动游戏。
flex与c#聊天代码.zip(69.7 KB, 下载次数: 144) |