2019独角兽企业重金招聘Python工程师标准>>>

实验功能:

  1. 设计程序,分别构建通信的两端:服务器端和客户端应用程序,套接字类型为面向连接的Socket,自己构建双方的应答模式,实现双方的数据的发送和接收(S发给C,C发给S)。

  2. 服务端程序能响应单个或任意多个客户端连接请求;服务端能向单个客户发送消息,支持群发消息给所有客户端;

  3. 通信的双方具备异常响应功能,包括对方异常退出的处理。如果客户端退出,服务器有响应;反之亦然。

  4. 客户端之间直接通信,C与C之间直接通信(不是通过S传递)。

设计思路:

  1. 服务器设计思路:服务器的设计是这次实验最复杂的部分,因为服务器的功能比较多。作为服务器,它要可以同时与多个客户端连接,为每一个连接的客户端创建一个通信Socket,自己还要有一个Socket用于监听客户端的连接请求;服务器要创建一个数据结构用于保存连接进来的客户端的信息(Socket和客户端的名字);服务器要将连接进来的客户端显示出来,用户可以根据显示出来的用户列表来向指定的客户端发信息;服务器要能及时地刷新客户端列表,当有新的客户端连接进来或是退出的时候要及时通知所有的客户端并刷新自己的客户端列表;服务器要能接收所有的客户端的信息,并将信息无错地转发给指定的客户端。

  2. 客户端设计思路:客户端的设计相对于服务器来说的话对会比较简单一点。客户端要有接收服务器信息的功能,但客户端只向服务器发信息,客户端通过服务器的转发功能向其它的客户端发送信息。客户端要可以处理服务器发过来的信息,还要有数据结构用来保存所有客户端的名字,并将所有客户端名字列表显示出来。可以指定客户端列表里面的多个项来向不同的客户端发信息。

  3. 通信数据处理:无论是服务器发给客户端,还是客户端发给服务器的数据,双方都要进行处理。对于不用的类型的数据要设计不用的标志信息,当双方收到信息后跟据标志信息进行不同的处理。数据可以分为三种 :

    a)登陆信息。这类信息提示有新的客户端连接进来。该信息由客户端首先发给服务器,服务器收到后会更新自己的在线客户端列表,增加与该客户端通信的Socket和名字,并将该信息转发给所有在线的客户端,提醒客户端即时更新客户端列表。这类信息以“login,客户端名”的形式发送。

    b)退出信息。这类信息提示发信息的客户端即将退出服务器。该信息由客户端首先发给服务器,服务器收到后会更新自己的在线客户端列表,删除与该客户端通信的Socket和名字,并将该信息转发给所有在线的客户端,提醒客户端即时更新客户端列表。这类信息以“logout,客户端名”的形式发送。

    c)通信信息。这类信息提示发送信息的客户端向在线的某个客户端或是服务器发起了通信,也可以是服务器与某个客户端发起了通信。如果该信息是服务器发给客户端或是客户端发给服务器,则直接发送,不用经过转发;如果是客户端向另一个客户端发送信息,则是先发给服务器,服务再转发给指定的客户端。这类信息以“talk,目的客户端名,发送的信息”的形式发送。

  4. 线程的设计思路:在服务器方面,需要一个程专门用于监听客户端的连接请求,对于连接进来的每一个客户端,还要创建一个线程用于接收信息,程序的主线程用于向不同的客户端发送信息,所以服务器至少需要要n+2(n>=0)个线程;在客户端方面,需要一个线程用于接收服务的信息,还要一个线程用于向服务器发送信息,所以只需要2个线程。

  5. 信息无边界问题:由于这里用的C#里面原始Socket套接字,所以在数据收发的过程中会出现无边界的问题。有时服务器向客户端发送多条不同类型的信息,客户端会把它们合并在一起,当成一条信息处理。为了提取不同类型的信息,发送信息之前要为每一条信息加特定的结束符。

  6. 客户端之间直接通信问题:为了实现客户端之间的直接通信,客户端之间必须知道其它客户端的IP和端口,这可以通过服务器的转发得到客户端之间的IP和端口。客户端也必须有一个自己可用的端口号用来和其它客户端之间的通信,所以除了第一次的客户端与服务器的连接以外,客户端即是服务器也是客户端。

服务器处理不同类型信息代码:

 string[] splitString = receiveString.Split(',');             //分割字符switch (splitString[0].ToLower()){case  "login":                            // 登陆信息user.username = splitString[1];userList.Add (user);                  // 增加用户列表AddItemToListBox (user.username);     // 刷新用户列表sendToAllClient (user,receiveString); // 通知所有在线用户FirstLogin (user);break; case  "logout":                           // 退出信息DeletItemInListBox (user.username);  sendToAllClient (user,receiveString);// 通知所有在线用户 RemoveUser (user);                   // 删除用户信息UserCount (--usercount);             // 刷新用户列表break; case  "talk":                            // 对话信息multMessage (user,receiveString);    // 转发对话break; default: sendMessageTorichBox ("不知道什么意思!");break; }

服务器监听客户端代码:

private  void button1_Click(object sender, EventArgs e){isNormalExit  = false;buttu_richBoxDelegate  d = buttu_richBox;       // 委托事件try {myListener.Listen (10);                          // 开始监听richTextBox1.Invoke(d,"成功监听.");           // 成功监听} catch{richTextBox1.Invoke(d,"监听失败。");         }Thread mhThread = new Thread(ListenClientConnect);  // 创建新的线程mhThread.IsBackground = true;                       // 设置为后台线程mhThread.Start ();button1.Enabled=false;                              // 开始监听按钮不可用button2.Enabled= true;                                }

服务器接受客户端代码:

private void ListenClientConnect ()
{Socket newClient =null;While (isNormalExit==false){
try {newClient = myListener.Accept();          // 接受客户端if(isNormalExit == true)                  // 如果服务器停止监听{ newClient.Close();                     // 关闭Socketusercount = 0;UserCount(usercount);Break;}}Catch{break;}User user = new User(newClient);                 // 保存客户端列表Thread threadReceive = new Thread(ReceiveData);  // 创建新的线程threadReceive.IsBackground=true;                 //设置为后台线程threadReceive.Start(user);                       // 开始线程UserCount(++usercount);                         // 客户端人数加1}}

客户端连接服务器代码:

Private  void button1_Click(object sender, EventArgs e)
{  button1.Enabled = false;client  = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);                              //新建套接字AddrichTextBox1Massage d = sendrichTextBox1Massage;Try {String  name = Dns.GetHostName();                     // 获得计算机的名字IPHostEntry me = Dns.GetHostEntry (name);             //获得计算机IPforeach(IPAddress ips in me.AddressList){Try { IPEndPoint ep = new  IPEndPoint(ips, 8889);  client.Connect(new IPEndPoint(ips, 8889));      // 连接服务器break;}catch{//若获取的IP是vs6的话
}}client.Send(Encoding.UTF8.GetBytes("login," + textBox1.Text));//向服务器发信息Thread threadReceive = new Thread(new ThreadStart(ReceiveData));//创建新线程threadReceive.IsBackground = true;                           // 设置为后台线程threadReceive.Start();                                       //开始线程}

客户端接受服务器信息代码:

private void ReceiveData(){AddrichTextBox1Massage d = sendrichTextBox1Massage;int receiveLength;while(isExit==false){try{receiveLength = client.Receive(result);             //开始接收信息recieveMessage=Encoding.UTF8.GetString(result,0,receiveLength);}catch{if (isExit == false){richTextBox1.Invoke(d, "与服务器失去联系。"); client.Shutdown(SocketShutdown.Both);            // 关闭套接字client.Close();}break;}string[] splitString = recieveMessage.Split(',');         //处理信息string command = splitString[0].ToLower();switch(command) {case "login":AddOnline(recieveMessage);               // 登陆信息break;case "logout": RemoveUserName(splitString[1]);        // 退出信息break;case "talk": richTextBox1.Invoke(d, "["+splitString[1] + "]对我说: " + splitString[2]);                         // 对话信息break;default: richTextBox1.Invoke(d,"不知什么意思。"); break;} }LostConnect();                                               //关闭连接}

客户端监听其它客户端代码:

private void ServerReceive(Object client)
{AddrichTextBox1Massage d = sendrichTextBox1Massage;Socket myClientSocket = (Socket)client;byte[] str =new byte[1024];while (true) {try{int n = myClientSocket.Receive(str);richTextBox1.Invoke(d, Encoding.UTF8.GetString(str, 0, n));break;}catch {myClientSocket.Close();//richTextBox1.Invoke(d, "接收消息失败!");break;}}myClientSocket.Close();}

程序运行效果:

  1. 服务器运行界面:

  2. 有客户端连接进服务器:

    在线客户列表显示了连接进的客户端的名字,在线客户人数显示为3人

    上图表示有3个客户端连接进了服务器。

  3. 服务器向客户端发送信息:

    服务器向在线客户列表里的2个客户同时发了信息,2个客户端收到了正确的信息。

  4. 客户端的启动界面:

    客户端自动生成用户的名字。

  5. 客户端登陆的界面:

    客户端显示连接成功,并刷新在线用户列表。

  6. 多个客户端连接服务器时的界面:

    当有多个客户端与服务器连接时,客户端会自动更新在线用户列表。

  7. 客户端向其它客户端发TCP信息:

    客户端可以同时向服务器和多个客户端发送信息。

  8. 客户端接收来自其它客户端的TCP信息:

    接收的信息是其它客户端直接发过来的,不经过服务器的转发。

  9. 客户端退出时:

    客户端退出时,服务器会知道退出的用户,并把该客户端移出列表,同时发信息通知其它的客户端,使它们可以及时地更新用户列表。

  10. 服务器退出时:

    当服务器退出时,所有的客户端会提示与服务器失去联系,并将在线用户列表清空。

转载于:https://my.oschina.net/u/1540055/blog/280470

C#利用Socket实现客户端之间直接通信相关推荐

  1. 利用Socket 本地和服务器之间通信(小白萌新适用之绝对能运行版)

    Java利用Socket 实现本地和服务器之间通信(小白萌新适用之绝对能运行版) 常规部署 1.先在自己本地跑通 客户端: Socket s = new Socket("localhost& ...

  2. Java中利用socket实现简单的服务端与客户端的通信(中级)——实现任意双向通信

    本文计划采用socket实现客户端和服务端的任意双向通信,即客户端可以随时给服务端发消息,服务端也可以随时给客户端发消息,最终结果就是一个类似与QQ的聊天软件的功能. 以下代码可以直接拷贝到Eclip ...

  3. Java中利用socket实现简单的服务端与客户端的通信(基础级)

    在上一篇文章中,简单的介绍了java中入门级的socket编程,简单的实现了客户端像服务器端发送数据,服务器端将数据接收并显示在控制台,没有涉及多线程.上一篇文章的链接:Java中利用socket实现 ...

  4. Java中利用socket实现简单的服务端与客户端的通信(入门级)

    Java编程中,要想要使用网络通信,就离不开Socket编程,在此对socket进行简单的介绍.首先声明,这是一个入门级的介绍,仅仅简单的实现了客户端向服务端发送数据,服务端正常的接收数据,当接收到特 ...

  5. Socket代码实现服务端 和 客户端之间通信

    服务端代码 // Socket_connection.cpp : 此文件包含 "main" 函数.程序执行将在此处开始并结束. // #ifndef UNICODE #define ...

  6. TCP:利用Socket编程技术实现客户端向服务端上传一个图片。

    问题: 利用Socket编程技术实现客户端向服务端上传一个图片的程序. 客户端: import java.io.*; import java.net.Socket;public class clien ...

  7. Socket实现服务器端与客户端之间通信(输入文字聊天)

    用Socket实现服务器端与客户端之间通信 需求: 键盘输入文字使服务器端与客户端可以实现文字通信. 使用的是TCP协议. TCP协议 客户端 创建Socket连接服务端(指定ip地址,端口号)通过i ...

  8. Http、Socket、WebSocket之间联系与区别

    一.WebSocket和Socket区别 可以把WebSocket想象成HTTP(应用层),HTTP和Socket什么关系,WebSocket和Socket就是什么关系.HTTP 协议有一个缺陷:通信 ...

  9. php socket 握手,python Socket之客户端和服务端握手详细介绍

    这篇文章主要为大家详细介绍了python Socket之客户端和服务端握手,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 简单的学习下利用socket来建立客户端和服务端之间的连接并且发送数据 1 ...

最新文章

  1. linux开启防火墙挂载nfs
  2. 因滚动条出现而导致页面晃动的解决方案
  3. hdu 2544最短路 Floyd算法
  4. MySql中 delimiter 详解
  5. 在Win7虚拟机下搭建Hadoop2.6.0伪分布式环境
  6. 为iPhone 12上市做准备,台积电月底前投产A14 Bionic芯片
  7. php数字转千分制,JS实现金额千分制的转换以及还原
  8. centos7卸载docker_使用 Docker 部署 Spring Cloud 项目详细步骤
  9. sigar 网络 java_java-Sigar网络速度
  10. matlab2018历史命令在哪,2018美赛准备之路——Matlab基础——命令行功能函数
  11. OpenCore配置文字说明(第二版)基于056(03-02官方正式版)
  12. 编程英语单词1.编程常用英语词汇大全
  13. 国外变电站3d可视化技术发展_盘点:测量技术五大发展趋势,含3D扫描
  14. PG 异常状态- active+undersized+degraded
  15. 普及!cmnet、cmiot还傻傻分不清楚?APN设置看看这一篇就够了!!
  16. 浏览器性能对比测试技术研究与应用
  17. RK3588 ssh Failed to start OpenBSD Secure Shell server 以及E: Sub-process /usr/bin/dpkg returned无法下载软件
  18. 海康威视SDK登录失败,错误码为8
  19. angelababy都靠它保持身材,只需10秒随时随地喝到新鲜果汁!
  20. unity安卓应用名称多语言本地化

热门文章

  1. 【代码笔记】iOS-下拉选项cell
  2. [递推] hihocoder 1239 Fibonacci
  3. 关于base64编码的原理及实现
  4. Go学习笔记—多线程
  5. antd表格显示分页怎么取消_真相!Word里怎么也删不掉的文档空白页原来是这样...
  6. centos上使用高版本gcc、g++
  7. 黑盒法测试c语言,黑盒测试用例练习题.pdf
  8. C++提取PDF页成BMP图片
  9. Error(6,35)java: 程序包 不存在,解决办法
  10. 用户与硬件之间的接口