上一节给大家演示了建立连接的关键代码,连接建立好后,就可以进行数据传输了。数据传输包含从服务器端到客户端和从客户端到服务器端,两者差别不大。

数据的传输,TcpClient的GetNetworkStream是关键,通过它我们可以得到NetworkStream网络流,客户端和服务器主要的工作就是对其读出和写入。关于如何构造稳定且性能好的网络应用,如何进行复杂的封包和解包,这里我们不考虑,我们使用StreamReader和StreamWriter来封装NetStream,读取和写入的代码如下

 1 TcpClient client;
 2 StreamReader sr;
 3 StreamWriter sw;
 4 this.userName = "";
 5 NetworkStream netStream = client.GetStream();
 6 sr = new StreamReader(netStream, System.Text.Encoding.UTF8);
 7 sw = new StreamWriter(netStream, System.Text.Encoding.UTF8);
 8 //读取数据
 9 string output=sr.ReadLine();
10 //写入数据
11 string input="";
12 sw.WriteLine();
13 sw.Flush();

客户端和服务器的通信一般是由客户端向服务器端发请求,服务器端接受请求并处理,再将结果重新发回客户端

发送请求和应答的协议格式可以自己定义,游戏中使用的协议格式为  命令,参数1,参数2......

先看一下客户端请求登录

 1 service.SendToServer("Login," + textBoxName.Text.Trim());
 2 class Service
 3 {
 4 ListBox listbox;
 5 StreamWriter sw;
 6 public Service(ListBox listbox, StreamWriter sw)
 7 {
 8     this.listbox = listbox;
 9     this.sw = sw;
10 }
11 public void SendToServer(string str)
12 {
13     sw.WriteLine(str);
14     sw.Flush();
15 }
16 }

服务器接受请求并处理,一般来说是根据不同的请求创建不同的线程进行处理,见本节后半部分
 1 private void ReceiveData(object obj)
 2 {
 3     //User类封装了TcpClient,StreamReader和StreamWriter
 4     User user = (User)obj;
 5     TcpClient client = user.client;
 6     string receiveString = null;
 7     receiveString = sr.ReadLine();
 8     service.SetListBox(string.Format("来自{0}:{1}", user.userName, receiveString));
 9     string[] splitString = receiveString.Split(',');
10     switch (splitString[0])
11     {
12         case "Login":
13             user.userName = string.Format("[{0}--{1}]", splitString[1], client.Client.RemoteEndPoint);
14             service.SendToOne(user, "Welcome");
15             break;
16         default:
17             break;
18     }
19 }
20 

 1 class Service
 2 {
 3         private ListBox listbox;
 4         private delegate void SetListBoxCallback(string str);
 5         private SetListBoxCallback setListBoxCallback;
 6         public Service(ListBox listbox)
 7         {
 8             this.listbox = listbox;
 9             setListBoxCallback = new SetListBoxCallback(SetListBox);
10         }
11         public void SetListBox(string str)
12         {
13             if (listbox.InvokeRequired)
14             {
15                 listbox.Invoke(setListBoxCallback, str);
16             }
17             else
18             {
19                 listbox.Items.Add(str);
20                 listbox.SelectedIndex = listbox.Items.Count - 1;
21                 listbox.ClearSelected();
22             }
23         }
24         public void SendToOne(User user, string str)
25         {
26             try
27             {
28                 user.sw.WriteLine(str);
29                 user.sw.Flush();
30                 SetListBox(string.Format("向{0}发送{1}", user.userName, str));
31             }
32             catch
33             {
34                 SetListBox(string.Format("向{0}发送信息失败", user.userName));
35             }
36         }
37  }
服务器负责监听并根据不同的用户启动不同的线程
 1 IPAddress localAddress;
 2 int port = 51888;
 3 TcpListener myListener;
 4 Service service = new Service(listbox);
 5 IPAddress[] addrIP = Dns.GetHostAddresses(Dns.GetHostName());
 6 localAddress = addrIP[0];
 7 myListener = new TcpListener(localAddress, port);
 8 myListener.Start();
 9 service.SetListBox(string.Format("开始在{0}:{1}监听客户连接", localAddress, port));
10 ThreadStart ts = new ThreadStart(ListenClientConnect);
11 Thread myThread = new Thread(ts);
12 myThread.Start();

ListenClientConnect方法
 1 while (true)
 2 {
 3     TcpClient newClient = null;
 4     try
 5     {
 6        newClient = myListener.AcceptTcpClient();
 7     }
 8     catch
 9     {
10        break;
11     }
12     User user = new User(newClient);
13     userList.Add(user);
14     service.SetListBox(string.Format("{0}进入", newClient.Client.RemoteEndPoint));
15     service.SetListBox(string.Format("当前连接用户数:{0}",userList.Count));
16     //basilwang 2008-09-06 to receive data from client
17     ParameterizedThreadStart pts = new ParameterizedThreadStart(ReceiveData);
18     Thread threadReceive = new Thread(pts);
19     threadReceive.Start(user);
20 }

此处的启用了ParameterizedThreadStart 线程处理带参数的ReceiveData方法,主要是防止同客户端传输数据的过程出现的异常不能正确处理导致线程崩溃,每一个客户端分配一个线程可以保证客户端各自的独立性;同时ParameterizedThreadStart允许传递参数。

至此我们完成了一个简单的服务器客户端应答,希望能对初学者有所帮助。

文件下载

基于TCP的网络游戏黑白棋系列(二):数据传输相关推荐

  1. 基于SDL的C++黑白棋

    https://apriljia.com/2018/07/30/%E5%9F%BA%E4%BA%8Esdl%E7%9A%84c%E9%BB%91%E7%99%BD%E6%A3%8B/ 写了一个基于SD ...

  2. TCP/IP网络编程之基于TCP的服务端/客户端(二)

    回声客户端问题 上一章TCP/IP网络编程之基于TCP的服务端/客户端(一)中,我们解释了回声客户端所存在的问题,那么单单是客户端的问题,服务端没有任何问题?是的,服务端没有问题,现在先让我们回顾下服 ...

  3. 基于Python实现的黑白棋强化学习模型

    资源下载地址:https://download.csdn.net/download/sheziqiong/85658862 一.基本原理 1. 强化学习 强化学习是指一类从(与环境)交互中不断学习的问 ...

  4. 基于Python的Reversi黑白棋游戏设计与开发

    摘 要 黑白棋是一个相当易学,而且很受欢迎的游戏.近年来,随着机器性能的提高和相关理论的完善,人工智能这一领域变得越来越重要,在实际生活中的运用也越来越广泛.为了学习简单的人工智能,我决定用Pytho ...

  5. Python实现蒙特卡洛树黑白棋完整代码

    Python实现的基于蒙特卡洛树搜索的完整代码 最终效果:在控制台输入输出,实现3种玩家(AI或者人类或者随机)的对弈 目录 一.黑白棋简介 二.蒙特卡洛树搜索简介 1.蒙特卡洛树搜索Monte Ca ...

  6. QT示例:基于TCP点对点Socket通讯

    QT示例:基于TCP点对点通讯 一. 概述 二.TCP 协议工作原理 三.TCP 编程模型 四.基于TCP点对点通讯示例 1.客户端 2.客户端Client示例 3.服务器 4.服务器server示例 ...

  7. TCP/IP网络编程之基于TCP的服务端/客户端(一)

    TCP/IP网络编程之基于TCP的服务端/客户端(一) 理解TCP和UDP 根据数据传输方式的不同,基于网络协议的套接字一般分为TCP套接字和UDP套接字.因为TCP套接字是面向连接的,因此又称为基于 ...

  8. 北京峰会系列二|基于SPDK的UDisk全栈优化

    今天给大家带来的是UCloud基于SPDK的UDisk全栈优化解决方案分享.通过介绍UDisk如何结合SPDK(包括SPDK vhost虚拟化方案)来进行端到端IO路径上的CPU.网络.磁盘性能的优化 ...

  9. Java学习系列(十六)Java面向对象之基于TCP协议的网络通信

    TCP/IP的网络分层模型:应用层(HTTP/FTP/SMTP/POPS...),传输层(TCP协议),网络层(IP协议,负责为网络上节点分配唯一标识),物理层+数据链路层). IP地址用于标识网络中 ...

最新文章

  1. ES和JS的区别,以及JavaScript的基本组成
  2. OVS DPDK--virtqueue(十七)
  3. 我的中年危机来得很自然
  4. 用J-Link烧写u-boot到Nor Flash—— 韦东山嵌入式Linux视频学习笔记04
  5. linux 提取ko文件,Linux获取so/ko文件版本号教程
  6. Bash脚本教程之变量
  7. C#设计模式(9)——装饰者模式(Decorator Pattern)
  8. linux 看防火墙的启停日志,LINUX下防火墙iptables的日志管理
  9. 大数据文本分析的应用场景有哪些?
  10. js基础练习:实现资料查找
  11. ubuntu装机必备+主题美化
  12. 566.重塑矩阵(力扣leetcode) 博主可答疑该问题
  13. 数字图像处理-冈萨雷斯(学习笔记)
  14. 【操作系统】进程通信
  15. 漫画聚合阅读器Tachidesk
  16. Random类:用来产生随机数字
  17. Avatarify-人脸驱动项目在Linux环境中的实现
  18. 阿里巴巴Java成神之路-笔记(8)动态代理
  19. vue 移动端适配flexible.js使用方法
  20. MATLAB绘图(特殊二维)

热门文章

  1. supervisor简介
  2. [原]Java程序员的JavaScript学习笔记(1——理念)
  3. 如何为Linux系统中的SSH添加双重认证
  4. 浅谈我对 jQuery 的了解
  5. 8月23号,来上海整整一年
  6. 重装64位WIN7之后再装KUBUNTU遇到的问题
  7. Q142:PBRT-V3,交点处各种微分的求解(三角形,3.6章节)
  8. 《An Introduction to Ray Tracing》—— 3.3 Ray-Surface Intersections
  9. android jason mysql,php-从android通过JSON到mysql阿拉伯语
  10. android修改代码后运行不生效,Android Studio使用Kotlin时,修改代码后运行不生效问题...