博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Socket网络编程(3)--两端通信
阅读量:5987 次
发布时间:2019-06-20

本文共 10472 字,大约阅读时间需要 34 分钟。

     上篇博文:

     介绍了客户端连接服务端,一对一,多对一的情况,下面实现服务器接收消息的功能。LZ这些弄的比较慢,也是边学习,边动手实现的。具体步骤在注释中写的比较清楚,不懂的可以留言,LZ会尽快回复。共同学习,共同进步。

接收消息时机

      什么时候接收消息?当服务器开始监听,有客户端连接,并且连接成功,此时负责通信的Socket已经创建,此时就可以接收消息了,可以通过Socket的Receive()方法接收消息。

1        // 摘要: 2         //     从绑定的 System.Net.Sockets.Socket 套接字接收数据,将数据存入接收缓冲区。 3         // 4         // 参数: 5         //   buffer: 6         //     System.Byte 类型的数组,它是存储接收到的数据的位置。 7         // 8         // 返回结果: 9         //     接收到的字节数。10         //11         // 异常:12         //   System.ArgumentNullException:13         //     buffer 为 null。14         //15         //   System.Net.Sockets.SocketException:16         //     试图访问套接字时发生错误。 有关更多信息,请参见备注部分。17         //18         //   System.ObjectDisposedException:19         //     System.Net.Sockets.Socket 已关闭。20         //21         //   System.Security.SecurityException:22         //     调用堆栈中的调用方没有所需的权限。23         public int Receive(byte[] buffer);
View Code

     上面代码介绍了Receive方法接收参数及返回值。

1  private void ListenConn(object o) 2         { 3             //将参数o 转化为监听的socket 4             Socket socketListener = o as Socket; 5             //写入循环 每一个连接就创建一个通信用的socket 6             while (true) 7             { 8                 //当有客户端连接成功 创建通信用的socket 9                 Socket connSocket = socketListener.Accept();10                 string ip = connSocket.RemoteEndPoint.ToString();11                 ShowMsg(ip + " " + DateTime.Now.ToString() + " 连接成功");12                //创建一个新线程去接收消息13                 Thread th = new Thread(ReceiveMsg);14                 th.Start(connSocket);15 16             }17 18         }

接收消息的代码:

1   //接收客户端的消息 2         private void ReceiveMsg(object o) 3         { 4             Socket connSocket = o as Socket; 5  6             //通信用的socket连接成功 就可以接收消息了 7             byte[] buffer = new byte[1024 * 1024 * 5];//5M缓存 8             while (true) 9             {10                 //count是当前接收的字节个数11                 int count = connSocket.Receive(buffer);12                 string ip = connSocket.RemoteEndPoint.ToString();13                 //判断接收到的字节个数 是0表示客户端关闭了14                 if (count > 0)15                 {16 17                     //将字节转换为字符串18                     string msg = Encoding.UTF8.GetString(buffer, 0, count);19                     ShowMsg(ip + " " + DateTime.Now.ToString() + "\r\n" + msg);20                 }21                 else22                 {23                     //socket没办法发送空消息 如果收到空消息 客户端关闭24                     ShowMsg(ip + ":" + "断开连接");25                     connSocket.Close();26                     break;27 28                 }29 30             }31 32         }

测试:仍然用telnet命令来测试:telnet 127.0.0.1 50000

     测试结果:多对一,一对一,发送消息正常,关闭客户端,服务端正常显示哪个客户端断开连接。

     服务器端所有代码:

1 using System;  2 using System.Collections.Generic;  3 using System.ComponentModel;  4 using System.Data;  5 using System.Drawing;  6 using System.Linq;  7 using System.Net;  8 using System.Net.Sockets;  9 using System.Text; 10 using System.Threading; 11 using System.Threading.Tasks; 12 using System.Windows.Forms; 13  14 namespace Wolfy.ChatServer 15 { 16     public partial class Server : Form 17     { 18         public Server() 19         { 20             InitializeComponent(); 21             //不让其检查跨线程的操作 22             Control.CheckForIllegalCrossThreadCalls = false; 23         } 24         //存放endpoin和通信用的socket 25         Dictionary
dic = new Dictionary
(); 26 private void btnSend_Click(object sender, EventArgs e) 27 { 28 ServerSendMsg(this.txtInputMsg.Text); 29 } 30 ///
31 /// 服务器给客户端发送消息 32 /// 33 private void ServerSendMsg(string msg) 34 { 35 //服务器给客户端发消息 36 string userkey = comboBoxEndpoint.Text; 37 if (!string.IsNullOrEmpty(userkey)) 38 { 39 ShowMsg(msg); 40 byte[] buffer = Encoding.UTF8.GetBytes(msg); 41 dic[userkey].Send(buffer); 42 msg = ""; 43 } 44 else 45 { 46 MessageBox.Show("请选择客户端"); 47 } 48 } 49 50 private void btnStartService_Click(object sender, EventArgs e) 51 { 52 //服务器ip地址 53 IPAddress ip = IPAddress.Parse(txtIPAddress.Text); 54 //ip地址和端口 55 IPEndPoint endpoint = new IPEndPoint(ip, int.Parse(txtPort.Text)); 56 //创建用于监听的socket 57 Socket socketListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 58 //绑定ip和端口 59 socketListener.Bind(endpoint); 60 //开始监听 限制连接数 最多可以连接10个 61 socketListener.Listen(10); 62 ShowMsg("开始监听......"); 63 //创建线程 去监听连接 64 Thread th = new Thread(ListenConn); 65 //将线程变为后台线程 66 th.IsBackground = true; 67 th.Start(socketListener); 68 } 69 private void ListenConn(object o) 70 { 71 //将参数o 转化为监听的socket 72 Socket socketListener = o as Socket; 73 //写入循环 每一个连接就创建一个通信用的socket 74 while (true) 75 { 76 //当有客户端连接成功 创建通信用的socket 77 Socket connSocket = socketListener.Accept(); 78 string ip = connSocket.RemoteEndPoint.ToString(); 79 ShowMsg(ip + " " + DateTime.Now.ToString() + " 连接成功"); 80 //连接成功后加入字典 81 dic.Add(ip, connSocket); 82 comboBoxEndpoint.Items.Add(ip); 83 //创建一个新线程去接收消息 84 Thread th = new Thread(ReceiveMsg); 85 th.Start(connSocket); 86 } 87 88 } 89 //接收客户端的消息 90 private void ReceiveMsg(object o) 91 { 92 Socket connSocket = o as Socket; 93 94 //通信用的socket连接成功 就可以接收消息了 95 byte[] buffer = new byte[1024 * 1024 * 5];//5M缓存 96 while (true) 97 { 98 //count是当前接收的字节个数 99 int count = connSocket.Receive(buffer);100 string ip = connSocket.RemoteEndPoint.ToString();101 //判断接收到的字节个数 是0表示客户端关闭了102 if (count > 0)103 {104 //将字节转换为字符串105 string msg = Encoding.UTF8.GetString(buffer, 0, count);106 ShowMsg(ip + " " + DateTime.Now.ToString() + "\r\n" + msg);107 }108 else109 {110 //socket没办法发送空消息 如果收到空消息 客户端关闭111 ShowMsg(ip + ":" + "断开连接");112 connSocket.Close();113 break;114 }115 116 }117 118 }119 ///
120 /// 提示信息辅助方法121 /// 122 ///
123 private void ShowMsg(string msg)124 {125 this.txtMsgView.AppendText(msg + "\r\n");126 }127 128 private void txtInputMsg_KeyUp(object sender, KeyEventArgs e)129 {130 //如果用户按下了Enter键131 if (e.KeyCode == Keys.Enter)132 {133 //则调用 服务器向客户端发送信息的方法134 ServerSendMsg(this.txtInputMsg.Text);135 }136 }137 }138 }
View Code

客户端实现

     客户端创建的socket即负责连接又负责通信,所以这里和服务端不同。客户端连接、接收消息和发送消息代码如下:

1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Threading.Tasks; 9 using System.Windows.Forms;10 using System.Net.Sockets;11 using System.Net;12 using System.Threading;13 namespace Wolf.ChatClient14 {15     public partial class Client : Form16     {17         public Client()18         {19             InitializeComponent();20             //不让检查跨线程操作21             Control.CheckForIllegalCrossThreadCalls = false;22         }23         Socket socket;24         private void btnStartService_Click(object sender, EventArgs e)25         {26             //连接服务器的ip和端口27             IPAddress ip = IPAddress.Parse(txtIPAddress.Text);28             IPEndPoint endpoint = new IPEndPoint(ip, int.Parse(txtPort.Text));29             //客户端的socket即负责连接又负责通信30             socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);31             //连接服务器32             socket.Connect(endpoint);33             ShowMsg("连接成功......");34             //和服务器连接成功后就可以接收服务端的消息了35             Thread th = new Thread(ReceiveMsg);36             th.IsBackground = true;37             th.Start();38 39         }40         private void ReceiveMsg()41         {42             byte[] buffer = new byte[1024 * 1024 * 5];43             while (true)44             {45                 int count = socket.Receive(buffer);46                 string msg = Encoding.UTF8.GetString(buffer, 0, count);47                 ShowMsg(this.txtIPAddress.Text + ":" + this.txtPort.Text + "  " + DateTime.Now.ToString() + "\r\n" + msg);48             }49         }50         private void ShowMsg(string msg)51         {52             txtMsgView.AppendText(msg + "\r\n");53         }54         private void btnSend_Click(object sender, EventArgs e)55         {56             ClientSendMsg(this.txtInputMsg.Text);57         }58 59         /// 60         /// 客户端向服务端发送消息61         /// 62         /// 63         private void ClientSendMsg(string msg)64         {65             //向服务端发送消息66             if (socket != null)67             {68                 ShowMsg(msg);69                 byte[] buffer = Encoding.UTF8.GetBytes(msg);70                 socket.Send(buffer);71                 msg = "";72             }73             else74             {75                 ShowMsg("<<<
<请先连接服务器>
>>");76 }77 }78 79 private void txtInputMsg_KeyUp(object sender, KeyEventArgs e)80 {81 //如果用户按下了Enter键82 if (e.KeyCode == Keys.Enter)83 {84 //则调用 服务器向客户端发送信息的方法85 ClientSendMsg(this.txtInputMsg.Text);86 }87 }88 89 private void Client_FormClosing(object sender, FormClosingEventArgs e)90 {91 //客户端关闭 关闭socket92 socket.Shutdown(SocketShutdown.Both);93 }94 }95 }
View Code

测试结果:

 结语:

       边学习,边动手,实现了两端通信,目前支持一对一,多对一通信功能,代码中针对关闭客户端的情况还有bug,有待进一步修改。

转载于:https://www.cnblogs.com/wolf-sun/p/3330221.html

你可能感兴趣的文章
redis未授权访问漏洞利用
查看>>
linux ps 命令详解
查看>>
Java IO类库之PipedWriter
查看>>
UFT入门教程(2)—活动屏幕、运行次数及运行时间
查看>>
我的友情链接
查看>>
Windows Server 2008 R2 + FileZilla server的防火墙设置问题
查看>>
docker 常用命令
查看>>
spring data neo4j 中节点实体之间的关系在代码中怎样维护
查看>>
Java记录 -23- equals方法和双等号解析
查看>>
TurboMail邮件系统全新智能公告模块升级上线
查看>>
中小企业邮件网关,路在何方
查看>>
世界范围网络中断 祸起瞻博路由器
查看>>
Report Builder 3.0报表访问权限设置
查看>>
shrio 权限管理filterChainDefinitions过滤器配置
查看>>
linux网卡的详细配置
查看>>
sbc(六) Zuul GateWay 网关应用
查看>>
HBase Config File
查看>>
Circle Queue in C
查看>>
LVS环境搭建
查看>>
vmware安装ubuntu1404后鼠标左键无法使用的解决方法
查看>>