基于Http协议的网络五子棋实现

一.准备工作

  1.序言

做这个项目的目的是帮助大家理解http服务器是怎样运行的,所以我使用的方法只是为了实现核心http传输信息功能,并没有考虑数据的存储,以及安全性之类的东西。所以这个项目仅供学习参考,不喜勿喷。

 

这个项目的实现方法有很多很多,比如:

(1)jsp+application:直接使用jsp内置application对象来实现数据的暂存。

(2)servlet+redis:使用servlet来处理请求,使用redis来缓存数据。

以及还有很多其他方法,这里就不累赘了,为了方便大家理解,我就直接使用jsp的内置对象application来实现

  2.环境:

  • tomcat 9.0
  • jdk 1.8
  • unity2017.4

  3.相关知识:

服务器部分:

  • jsp:(java server page)即运行在服务器端的一个程序。


    <%@page import="java.lang.*"%> //需要导入的包 <%@ page language="java" contentType="text/html; charset=utf-8"pageEncoding="utf-8"%> //定义页面的字符编码,一般是支持中文的国际编码utf-8 <% java代码 %> //和普通的java一样、只是内置对象可以直接使用,不用定义 <html> html网页代码 //具体不详写 </html>

  • request:  jsp中存储有http请求的相关信息的一个内置对象。


    request.getParameter("表单属性名"); //获取http请求中的表单数据

  • response:  jsp中存储有服务器响应给浏览器客户端的相关信息的一个内置对象。


    response.getWriter().write("输出信息"); //获取响应的书写器,向客户端输出信息,和内置out对象一样

  • application:  jsp的一个内置对象,即可以直接使用,一个服务器项目只有一个application对象,服务器重启这个对象就会重置,当jsp转为servlet的java代码后,application会转为ServletContext对象,可以在servlet代码中使用request.getServletContext()来获取这个对象

application.setAttribute("属性名",属性值); //存储数据 application.getAttribute("属性名"); //获取数据

  • out:  jsp中内置的向客户端输出信息的对象,在servlet中是JspWriter对象。
out.write("输出信息");                //向客户端输出信息(先写入缓冲区)
out.flush();                //刷新缓冲区、执行后会将缓冲区的内容发送给客户端

  unity客户端部分:

  unity内置有一个WWW类,可以用来发送HTTP请求(当然也可以通过C#中有关HTTP协议的部分来实现),返回的WWW实例中存储有从服务器端返回的数据

注意:要想用unity的WWW类发送HTTP请求必须通过协程来实现

    发送HTTP请求:

  

WWWForm form = new WWWForm();        //新建一个表单
form.AddField("属性名", 属性值);        //向表单中添加字段
WWW www = new WWW("http://127.0.0.1:8080/Server/index.jsp", form);                //post方式发送HTTP请求


WWW www = new WWW("http://127.0.0.1:8080/Server/index.jsp?username=user&password=123");        //get方式发送HTTP请求 

    获取返回的信息:

String result = www.text                //获取www中的文本信息     
byte[] res = www.bytes;                //获取www中的二进制数据
AudioClip audioclip = www.GetAudioClip();            //获取www中的音频文件
MovieTexture movie = www.GetMovieTexture();            //获取www中的视频文件

  4. 具体开发

    服务器端(在项目文件夹Server下的index.jsp):

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<% 
        String x = request.getParameter("x");            //棋子的x坐标
        String y = request.getParameter("y");            //棋子的y坐标
        String id = request.getParameter("id");            //棋子的颜色(0代表黑色,1代表白色)
//如果发来的是黑棋信息,则在服务器端更新存储的黑棋信息,并将白棋信息发送给客户端 if(id.equals("0")) { application.setAttribute("black", x +","+ y); out.write((String)application.getAttribute("white")); out.flush(); } //如果发来的是黑棋信息,则在服务器端更新存储的黑棋信息,并将白棋信息发送给客户端 else if(id.equals("1")) { application.setAttribute("white", x +","+ y); out.write((String)application.getAttribute("black")); out.flush(); } %>

    unity客户端(客户端TakeChess脚本获取用户落棋的坐标,然后通过SenChessPos脚本发送给服务器端,随后将服务器端返回的对方的落棋坐标在本地显示出来):

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

/*
Bcoordinate:Vector2类型的变量,用来存储游戏中每回合的黑棋的下棋坐标
Wcoordinate:Vector2类型的变量,用来存储游戏中每回合的白棋的下棋坐标
*/
[RequireComponent(typeof(TakeChess))]       //挂上此脚本的物体必须要有TakeChess脚本,即游戏主逻辑脚本 
public class SendChessPos : MonoBehaviour {
    
    public float timer = 0.1f;                //客户端发送HTTP请求的间隔时间
    public GameObject infotext;            //通知连接信息的UI组件
    TakeChess takechess;                //游戏的主逻辑组件(脚本),期中存有每回合的黑白棋坐标
    // Use this for initialization
    void Start () {
        takechess = this.GetComponent<TakeChess>();       //获取主逻辑脚本组件 
    }
    
    // Update is called once per frame
    void Update () {
        timer -= Time.deltaTime;
        
        if (timer <= 0)
        {
            timer = 0.1f;
            StartCoroutine(SendChesspos());
        }
    }
    public void onClickBtn()
    {
        StartCoroutine(sendChesspos());
    }
       //发送HTTP请求的协程
    IEnumerator SendChesspos()
    {
        WWWForm form = new WWWForm();
        if(takechess.Bcoordinate != null)
        {
            form.AddField("x", (int)takechess.Wcoordinate.x);
            form.AddField("y", (int)takechess.Wcoordinate.y);
            form.AddField("id", 1);        //编号和服务器端统一
        }
        
        WWW www = new WWW("http://127.0.0.1:8080/Server/index.jsp", form);
       
        yield return www;            //等服务器响应后才执行后面的代码
       
        if (www.error != null)            //如果连接服务器出错,则显示出错的log信息
        {
            Debug.Log(www.error);
            yield return null;
        }

        else if(www.error == null)
        {
            string s = www.text;
            string[] pos = s.Split(',');        //按格式取出服务器发来的坐标
            int x = int.Parse(pos[0]);
            if(x != -1)
            {
                int y = int.Parse(pos[1]);
                takechess.Bcoordinate = new Vector2(x, y);
                takechess.infotext.text = "在线...";
            }  
            
            else
            {
                takechess.infotext.text = "等待连接...";
            }
        }
    }
}                    

  游戏的主逻辑TakeChess有很多实现方式,这个大家随便写一个就好了,到此,一个网络五子棋的基本网络功能部分就实现了。大家可以自己写一写试一下,如果过程中有问题可以QQ找我(1263415838)。

猜你喜欢

转载自www.cnblogs.com/Sukrfq/p/9117017.html