Socket异步通讯-Unity实现服务端、客户端和数据库

服务器端

Conn.cs
using System;
using System.Net;
using System.Net.Sockets;
using System.Collections;
using System.Collections.Generic;

public class Conn
{
	//常量
	public const int BUFFER_SIZE = 1024;
	//Socket
	public Socket socket;
	//是否使用
	public bool isUse = false;
	//Buff
	public byte[] readBuff = new byte[BUFFER_SIZE];
	public int buffCount = 0;
	//构造函数
	public Conn()
	{
		readBuff = new byte[BUFFER_SIZE];
	}
	//初始化
	public void Init(Socket socket)
	{
		this.socket = socket;
		isUse = true;
		buffCount = 0;
	}
	//缓冲区剩余的字节数
	public int BuffRemain()
	{
		return BUFFER_SIZE - buffCount;
	}
	//获取客户端地址
	public string GetAdress()
	{
		if (!isUse)
			return "无法获取地址";
		return socket.RemoteEndPoint.ToString();
	}
	//关闭
	public void Close()
	{
		if (!isUse)
			return;
		
		Console.WriteLine("[断开链接]" + GetAdress());
		socket.Close();
		isUse = false;
	}
}
Serv.cs
using System;
using System.Net;
using System.Net.Sockets;

public class Serv
{
	//监听嵌套字
	public Socket listenfd;
	//客户端链接
	public Conn[] conns;
	//最大链接数
	public int maxConn = 50;
	
	//获取链接池索引,返回负数表示获取失败
	public int NewIndex()
	{
		if (conns == null)
			return -1;
		for (int i = 0; i < conns.Length; i++)
		{
			if (conns[i] == null)
			{
				conns[i] = new Conn();
				return i;
			}
			else if (conns[i].isUse == false)
			{
				return i;
			}
		}
		return -1;
	}
	
	//开启服务器
	public void Start(string host, int port)
	{
		//链接池
		conns = new Conn[maxConn];
		for (int i = 0; i < maxConn; i++)
		{
			conns[i] = new Conn();
		}
		//Socket
		listenfd = new Socket(AddressFamily.InterNetwork,
		                      SocketType.Stream, ProtocolType.Tcp);
		//Bind
		IPAddress ipAdr = IPAddress.Parse(host);
		IPEndPoint ipEp = new IPEndPoint(ipAdr, port);
		listenfd.Bind(ipEp);
		//Listen
		listenfd.Listen(maxConn);
		//Accept
		listenfd.BeginAccept(AcceptCb, null);
		Console.WriteLine("[服务器]启动成功");
	}


	//Accept回调
	private void AcceptCb(IAsyncResult ar)
	{
		try
		{
			Socket socket = listenfd.EndAccept(ar);
			int index = NewIndex();
			
			if(index < 0)
			{
				socket.Close();
				Console.Write("[警告]链接已满");
			}
			else
			{
				Conn conn = conns[index];
				conn.Init(socket);
				string adr = conn.GetAdress();
				Console.WriteLine("客户端连接 [" + adr +"] conn池ID:" + index);
				conn.socket.BeginReceive(conn.readBuff, 
				                         conn.buffCount, conn.BuffRemain(),
				                         SocketFlags.None, ReceiveCb, conn);
			}
			listenfd.BeginAccept(AcceptCb,null);
		}
		catch(Exception e)
		{
			Console.WriteLine("AcceptCb失败:" + e.Message);
		}
	}

	private void ReceiveCb(IAsyncResult ar)
	{
		Conn conn = (Conn)ar.AsyncState;
		try
		{
			int count = conn.socket.EndReceive(ar);
			//关闭信号
			if(count <= 0)
			{
				Console.WriteLine("收到 [" + conn.GetAdress() +"] 断开链接");
				conn.Close();
				return;
			}
			//数据处理
			string str = System.Text.Encoding.UTF8.GetString(conn.readBuff, 0, count);
			Console.WriteLine("收到 [" + conn.GetAdress() +"] 数据:" + str);
			str = conn.GetAdress() + ":" + str;
			byte[] bytes = System.Text.Encoding.Default.GetBytes(str);
			//广播
			for(int i=0;i < conns.Length; i++)
			{
				if(conns[i] == null)
					continue;
				if(!conns[i].isUse)
					continue;
				Console.WriteLine("将消息转播给 " + conns[i].GetAdress());
				conns[i].socket.Send(bytes);
			}
			//继续接收	
			conn.socket.BeginReceive(conn.readBuff, 
			                         conn.buffCount, conn.BuffRemain(), 
			                         SocketFlags.None, ReceiveCb, conn);
		}
		catch(Exception e)
		{
			Console.WriteLine("收到 [" + conn.GetAdress() +"] 断开链接");
			conn.Close();
		}
	}
}
MainClass.cs
using System;
using System.Net;
using System.Net.Sockets;

class MainClass
{
	public static void Main(string[] args)
	{
		Console.WriteLine("Hello World!");
		Serv serv = new Serv();
		serv.Start("127.0.0.1", 1234);
		
		while (true)
		{
			string str = Console.ReadLine();
			switch (str)
			{
			case "quit":
				return;
			}
		}
	}
}

 

客户端

 

netAsyn.cs
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using UnityEngine.UI;

public class netAsyn : MonoBehaviour
{
    //服务器IP和端口
    public InputField hostInput;
    public InputField portInput;
    //显示客户端收到的消息
    public Text recvText;
    public string recvStr;
    //显示客户端IP和端口
    public Text clientText;
    //聊天输入框
    public InputField textInput;
    //Socket和接收缓冲区
    Socket socket;
    const int BUFFER_SIZE = 1024;
    public byte[] readBuff = new byte[BUFFER_SIZE];

    //因为只有主线程能够修改UI组件属性
    //因此在Update里更换文本
    void Update()
    {
        recvText.text = recvStr;
    }

    //连接
    public void Connetion()
    {
        //清理text
        recvText.text = "";
        //Socket
        socket = new Socket(AddressFamily.InterNetwork,
                         SocketType.Stream, ProtocolType.Tcp);
        //Connect
        string host = hostInput.text;
        int port = int.Parse(portInput.text);
        socket.Connect(host, port);
        clientText.text = "客户端地址 " + socket.LocalEndPoint.ToString();
        //Recv
        socket.BeginReceive(readBuff, 0, BUFFER_SIZE, SocketFlags.None, ReceiveCb, null);
    }

    //接收回调
    private void ReceiveCb(IAsyncResult ar)
    {
        try
        {
            //count是接收数据的大小
            int count = socket.EndReceive(ar);
            //数据处理
            string str = System.Text.Encoding.UTF8.GetString(readBuff, 0, count);
            if (recvStr.Length > 300) recvStr = "";
            recvStr += str + "\n";
            //继续接收	
            socket.BeginReceive(readBuff, 0, BUFFER_SIZE, SocketFlags.None, ReceiveCb, null);
        }
        catch (Exception e)
        {
            recvText.text += "链接已断开";
            socket.Close();
        }
    }

    //发送数据
    public void Send()
    {
        string str = textInput.text;
        byte[] bytes = System.Text.Encoding.Default.GetBytes(str);
        try
        {
            socket.Send(bytes);
        }
        catch { }
    }
}


数据库端:

public void HandleMsg(Conn conn, string str)
	{
		//获取数据
		if(str == "_GET")
		{
			string cmdStr = "select * from msg order by id desc limit 10;";  
			MySqlCommand cmd = new MySqlCommand(cmdStr, sqlConn);  
			try
			{
				MySqlDataReader dataReader = cmd.ExecuteReader(); 
				str = "";
				while (dataReader.Read())  
				{  
					str+= dataReader["name"] + ":" + dataReader["msg"] + "\n\r";
				}  
				dataReader.Close();
				byte[] bytes = System.Text.Encoding.Default.GetBytes(str);
				conn.socket.Send(bytes);
			}
			catch(Exception e)
			{
				Console.WriteLine("[数据库]查询失败 " + e.Message);
			}
		}
		//插入数据
		else
		{
			string cmdStrFormat = "insert into msg set name ='{0}' ,msg ='{1}';";
				string cmdStr = string.Format(cmdStrFormat, conn.GetAdress(), str);
			MySqlCommand cmd = new MySqlCommand(cmdStr, sqlConn);
			try
			{
				cmd.ExecuteNonQuery();
			}
			catch(Exception e)
			{
				Console.WriteLine("[数据库]插入失败 " + e.Message);
			}
		}
	}

对数据库的操作:登陆注册:

public User VerifyUser(MySqlConnection conn, string username,string password)
        {
            MySqlDataReader reader = null;
            try
            {
                MySqlCommand cmd = new MySqlCommand("select * from user where username = @username and password = @password", conn);
                cmd.Parameters.AddWithValue("username", username);
                cmd.Parameters.AddWithValue("password", password);
                reader = cmd.ExecuteReader();
                if (reader.Read())
                {
                    int id = reader.GetInt32("id");
                    User user = new User(id, username, password);
                    return user;
                }
                else
                {
                    return null;
                }
            }catch(Exception e)
            {
                Console.WriteLine("在VerifyUser的时候出现异常:"+e);
            }
            finally
            {
                if (reader != null) reader.Close();
            }
            return null;
        }
public void AddUser(MySqlConnection conn, string username, string password)
        {
            try
            {
                MySqlCommand cmd = new MySqlCommand("insert into user set username = @username , password = @password", conn);
                cmd.Parameters.AddWithValue("username", username);
                cmd.Parameters.AddWithValue("password", password);
                cmd.ExecuteNonQuery();
            }
            catch (Exception e)
            {
                Console.WriteLine("在AddUser的时候出现异常:" + e);
            }
        }
public bool GetUserByUsername(MySqlConnection conn, string username)
        {
            MySqlDataReader reader = null;
            try
            {
                MySqlCommand cmd = new MySqlCommand("select * from user where username = @username", conn);
                cmd.Parameters.AddWithValue("username", username);
                reader = cmd.ExecuteReader();
                if (reader.HasRows)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("在GetUserByUsername的时候出现异常:" + e);
            }
            finally
            {
                if (reader != null) reader.Close();
            }
            return false;
        }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kerven_HKW

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值