当前位置: 首页 > article >正文

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

0.前言

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

目录

  • 0.前言
  • 1.使用Socket搭建Server
    • 1.1Server端的Socket连接
    • 1.2 Server端接收Client的信息
    • 1.3 Server端接收信息后,处理信息
    • 1.4 Server端给Client端发送信息
    • 1.5 小结
  • 2.Client端 搭建Socket连接
    • 2.0 前言
    • 2.1 连接服务器
    • 2.2 Unity中怎么转换Json
  • 3.远程联机
    • 3.1SakuraFrp
    • 3.2 Client端

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


http://www.kler.cn/a/448149.html

相关文章:

  • ECharts柱状图-柱图42,附视频讲解与代码下载
  • 数智化医院分布式计算框架融合人工智能方向初步实现与能力转换浅析
  • MySQL内查询
  • kafka常用命令(持续更新)
  • leetcode45.跳跃游戏II
  • Linux系统的阻塞方式和非阻塞方式是什么意思?
  • 18个AI变现案例分享,每一个都可以作为副业赚睡后收入!
  • Vue.js前端框架教程9:Vue插槽slot用法
  • Java基础复习(二):面向对象编程
  • Apache POI练习代码
  • cocos creator制作2dTop-down游戏(虚拟摇杆、地图加载)
  • UI自动化-八大元素定位方法
  • 如何利用Python爬虫获得1688商品详情
  • 基于单片机的程控电源显示控制电路设计
  • 抓包之使用wireshark抓http2的包
  • R语言读取hallmarks的gmt文档的不同姿势整理
  • 【大语言模型】ACL2024论文-33 Johnny 如何说服大型语言模型越狱:通过人性化 LLMs 重新思考挑战 AI 安全性的说服技巧
  • 在 C# 中播放系统声音:蜂鸣声、星号声、问号声等
  • sql注入之union注入
  • STM32完全学习——CRC校验
  • IP地址格式解析(ipv4)
  • RabbitMQ中的Topic模式
  • JavaScript 中的 `parseInt()` 函数详解
  • vi或vim进行替换
  • 【Linux系统编程】:信号(2)——信号的产生
  • ChatGPT生成接口文档的方法与实践