C#游戏客户端编程

一、TCP客户端与服务器端通信

服务器初始化

(1)调用socket,创建文件描述符
(2)调用bind,将文件描述符与ip/port连接起来。若端口号已被占用,则bind失败
(3)调用listen,声明该文件描述符是服务器的一个文件描述符,为之后的accept做准备
(4)调用accept,并处于阻塞状态,等待客户端连接

建立连接

(1)调用socket,创建文件描述符
(2)调用connect,向服务器发起连接请求。
(3)connect会发送一个请求SYN段并阻塞等待服务器应答(第一次)
(4)服务器收到SYN,会给客户端发送一个确认应答的同时发送一个请求(SYN+ACK),表示同意建立连接(第二次)
(5)客户端收到客户端发的SYN+ACK段,表明客户端连接已建立成功,进入ESTABLISHED状态,从connect()。客户端再向服务器发送一个ACK段,服务器收到后则服务器端连接也建立成功,服务器也进入ESTABLISHED状态。
在这里插入图片描述

数据传输

(1)连接建立成功后,在同一连接、同一时刻,通信双方可同时写数据(全双工)
(2)服务器端从accept()返回后调用read()开始读数据,若没有数据则阻塞等待
(3)客户端调用write()向服务器发送数据请求,客户端收到之后调用read()处理请求,此过程服务器调用read()阻塞等待
(4)服务器调用write()将处理好的请求发送给客户端,再次调用read()等待下一个请求
(5)客户端收到后从read()返回,发送下一条请求,如此循环下去

断开连接

(1)没有数据处理了,则客户端调用close()关闭连接,给服务器端发送一个断开连接请求FIN段(第一次)
(2)服务器收到客户端的FIN段,给客户端发送一个确认应答ACK段表明同意断开连接,客户端收到ACK段并调用read()返回0,表明客户端连接已断开(第二次)
(3)read()返回0之后,服务器知道客户端已断开连接,它也调用close()关闭连接,给客户端发送一个断开连接请求FIN段(第三次)
(4)客户端接收到服务器端发送的FIN段,给服务器一个确认应答ACK段,表明同意断开连接。客户端进入TIME_WAIT状态,服务器收到客户端的ACK后则服务器断开连接。
在这里插入图片描述

二、编写网游客户端

  • 创建项目
    在这里插入图片描述
  • 基本界面设计
    在这里插入图片描述
  • 代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Net;
using System.Net.Sockets;
using System.Media;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WinFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private NetworkStream stream;
        private TcpClient tcpClient;

        SoundPlayer player = new SoundPlayer("D:/Fuchikami/nene/Lopu$ - So Cute~.mp3");
       
        Socket socket_send;
        void send_stream(string str)
        {
            System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
            System.Text.Encoding GBK = System.Text.Encoding.GetEncoding("GBK");
            byte[] buffer = GBK.GetBytes(str + "\n");
            stream.Write(buffer, 0, buffer.Length);
        }
       
        void receive_stream()
        {
            byte[] receive_data = new byte[1024];
            //定义编码格式
            System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);//为使用GB2312做准备
            System.Text.Encoding GBK = System.Text.Encoding.GetEncoding("GBK");
            if (stream.CanRead)
            {

                int len = stream.Read(receive_data, 0, receive_data.Length);
                string msg = GBK.GetString(receive_data, 0, receive_data.Length);

                string str = "\r\n";
                char[] str1 = str.ToCharArray();
                string[] messy_code = { "??[2J ", "[5m", "[44m", "[37;0m", "[1;33m", "[1;32m", "[1;31m" };
                string[] msg1 = msg.Split(str1);//以换行符为分隔符
                for (int j = 0; j < msg1.Length; j++)//逐行显示
                {

                    msg1[j] = msg1[j].Replace(messy_code[0], " ");
                    msg1[j] = msg1[j].Replace(messy_code[1], " ");
                    msg1[j] = msg1[j].Replace(messy_code[2], " ");
                    msg1[j] = msg1[j].Replace(messy_code[3], " ");
                    msg1[j] = msg1[j].Replace(messy_code[4], " ");
                    msg1[j] = msg1[j].Replace(messy_code[5], " ");
                    msg1[j] = msg1[j].Replace(messy_code[6], " ");
                    listBox1.Items.Add(msg1[j]);
                }
            }
        }



        private void button1_Click(object sender, EventArgs e)
        {

        }

        private void pictureBox1_Click(object sender, EventArgs e)
        {

        }

        private void button2_Click(object sender, EventArgs e)
        {
            tcpClient = new TcpClient();
            //套接字建立连接


            socket_send = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint point = new IPEndPoint(IPAddress.Parse("10.1.230.74"), 3900);
            socket_send.Connect(point);
            try
            {
                //向指定的IP地址的服务器发送连接请求
                tcpClient.Connect("10.1.230.74", 3900);
                listBox1.Items.Add("连接成功");
                stream = tcpClient.GetStream();
                receive_stream();//接收字节流并显示在屏幕上

            }
            catch
            {
                listBox1.Items.Add("服务器未启动");
            }
        }

        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (tcpClient.Connected)
            {
                string action = textBox1.Text.ToString();
                listBox1.Items.Add("输入的信息为:" + action);
                send_stream(action);
                receive_stream();

            }
            else
            {
                listBox1.Items.Add("连接已断开");
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {

            if (stream != null)
            {
                stream.Close();
                tcpClient.Close();
                socket_send.Close();
            }
            listBox1.Items.Add("退出游戏");
        }

        private void button4_Click(object sender, EventArgs e)
        {
            player.Load();
            player.Play();
        }
     

    }
}

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值