基于Socket实现客户端和服务端的Tcp通信(C#)

0.前言

使用C#和Unity实现复刻Liar’s bar中的功能
软件开发大作业
本系列文章用于记录与分享开发过程中使用到的知识点,以及常见错误
本文主要描述有关网络编程的内容

1.使用Socket搭建Server

1.1Server端的Socket连接

public static void waitClient{
	//ipv4地址,此处使用localhost
	string host = "127.0.0.1";
	//端口号,需要与其他端口占用不同,例如3306,8080等
	//client端与此处端口相同即可
	string port = "6657";
	
	//创建ip
	IPEndPoint pos = new IPEndPoint(IPAddress.Parse(host), port);
	Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
	listener.Bind(pos);
	//最多接收3个人的连接,参数可以改变
	listener.Listen(3);
	
	Socket sclient;
	String name;
	byte[] buffer = new byte[1024];
	Player p;
	int len;
	//监听客户端的连接
	while (true)
	{
		//接收到客户端连接 保存到sclient对象中
	    sclient = listener.Accept();
		//并给这个对象单独开一个监听线程,在文后会再详细说明
	    Thread listen = new Thread(new ParameterizedThreadStart(listenerClient));
	    listen.Start(sclient);
	}
}

static void Main(String[] args){
    //为等待客户端连接创建一个线程
	Thread wait = new Thread(new ThreadStart(waitClient));
	wait.Start();
}

1.2 Server端接收Client的信息

 static void listenerClient(Socket s)
 {
     byte[] buffer = new byte[1024];
     while (true)
     {
         Message msg;
         try
         {
             int len = s.Receive(buffer);
             string str = Encoding.UTF8.GetString(buffer, 0, len);
			 //根据&进行分割
			 //由于客户端和服务端发送信息有延迟,
			 //传输时在每个信息后面加&可以分清楚信息的范围
             foreach (string s in str.Split('&'))
             {
                 if (s.Length > 0)
                 {
                     //反序列成msg对象 发送的是json格式的数据
                     //这里用的是NewtonSoft.Json可以在NuGet引入依赖
                     msg = JsonConvert.DeserializeObject<Message>(s);
                         //将msg加入到queue中
                         //上锁 使线程同步
                         //这里的toDoListLock的声明为        
//private static readonly object toDoListLock = new object();
                         lock (toDoListLock)
                         {
                         //这里的toDoList的声明为:
//private static Queue<Message> toDoList = new Queue<Message>();
                             toDoList.Enqueue(msg);
                         }
                 }
             }
         }
         catch (SocketException)
         {//常见try-catch,不做过多赘述
             break;
         }
     }

 }
//常见Msg类
class Message
{
    public String type;
    public String info;
	//构造器
    public Message(string type, string info)
    {
        this.type = type;
        this.info = info;
    }
}

1.3 Server端接收信息后,处理信息

//也需要给本类启动一个线程,
//Thread toDo = new Thread(new ThreadStart(toDoListClient));
//toDo.start
 static void toDoListClientOperation()
 {
     while (true)
     {//循环监听,如果此时队列中无信息就进入下次循环
         if (toDoList.Count == 0)
         {
             continue;
         }
         //得到msg对象
         Message msg = toDoList.Dequeue();
         switch(msg.type){
         //根据类型进行对应操作即可 此处省略
         }
     }
 }

1.4 Server端给Client端发送信息

 static void sendMsg(string type, string info,Socket socket)
 {
     Message msg = new Message(type, info);
     string str = JsonConvert.SerializeObject(msg);
     //将json字符串转成字符数组并最后加上一个&
     //添加&的原因已在1.2中说明,此处省略
     byte[] bytes = Encoding.UTF8.GetBytes(str + '&');
     //发送信息
     socket.Send(bytes);
 }

1.5 小结

大体思路就是一个线程用于接收Client的连接,一个线程用于接收Client的信息,一个线程专门用于处理信息
面对Server端要被多个Client端连接时,可以创建数组保存这些Socket

2.Client端 搭建Socket连接

2.0 前言

由于Client端与Server端搭建类似,此处只写如何连接,后面的收发信息则不过多赘述

2.1 连接服务器

//与Server端保持一致
string host = "127.0.0.1";
string port = "6657";
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(host, port);

2.2 Unity中怎么转换Json

在Unity项目中引入NewtonSoft.Json.dll后发现经常会导致程序崩溃,
Unity中自带一个处理JSON的类:JsonUtility 类
常用API:
JsonUtility.ToJson(param)
JsonUtility.FromJson<>(param)

3.远程联机

这里简单提供一种思路:内网穿透
在代码实现方面与上面相同,只不过host和port要改变

3.1SakuraFrp

这里用SakuraFrp实现内网穿透
搭建时本机IP去看当前联网的属性中IPV4的地址
(注意:此时开启服务器的电脑本地IP不是127.0.0.1,要去Wlan那里看具体的ip是什么)
搭建选择TCP
附SakuraFrp的官方地址:https://www.natfrp.com/
Server端的ip填写ipv4的地址,端口就写搭建时开放的端口
(注:Server端电脑的端口应该设置为开放)
笔者曾使用该软件进行游戏联机,所以想到这里能用(doge)

3.2 Client端

启动SakuraFrp该隧道后,在日志信息中会给出映射的ip和端口
日志信息
冒号前面是host,后面是port。
则Client端的host=“211.149.167.185”,port=28821

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值