Socket通信(二)

程序下载地址:

http://download.csdn.net/detail/u010312811/9683748

1.基本流程

服务器:
(1)用指定的端口号和服务器的IP建立一个EndPoint对象
(2)建立一个Socket对象
(3)用Socket对象的Bind()方法绑定EndPoint
(4)用Socket对象的Listen()方法开始监听
(5)接受客户端的连接,用Socket对象的Accept()方法创建新的Socket对象用于和请求的客户端进行通信
(6)通信结束后一定要关闭Socket

客户端:
(1)用指定的端口号和服务器的IP建立一个EndPoint对象
(2)建立一个Socket对象
(3)用Socket对象的Connect()方法以上面建立的EndPoint对象作为参数,向服务器发出连接请求
(4)如果连接成功,就用Socket对象的Send()方法向服务器发送信息
(5)用Socket对象的Receive()方法接收服务器发来的信息
(6)通信结束后需要关闭Socket

2.功能及效果图: 

  • Server和Client进行封装,方便调用
  • 消息进行封装,消息收发利用Linq
  • 消息使用事件进行发布订阅,降低耦合度
  • 支持消息发送、文件发送(文件大小不超过10M)
  • 服务器端支持用户昵称,上下线提醒

3.服务器功能介绍:

(1)服务器开始监听:

  • 订阅消息接收事件
  • 订阅文件接收事件
  • 订阅用户的登陆、退出事件
 1    //服务器开始监听端口
 2    server.StartListen(txtIp.Text, int.Parse(txtPort.Text));
 3    //服务器接收到消息
 4    server.MessageReceived += server_MessageReceived;
 5    //服务器接收到文件
 6    server.FileReceived += server_FileReceived;
 7    //服务器订阅用户的登录退出事件
 8    server.UserLogIn += server_UserLogIn;
 9    server.UserLogOut += server_UserLogOut;
10 
11    txtMsgReceive.Text += "服务器开始监听!
";

(2)消息的发送:

  • 获取需要发送的消息
  • 将消息进行封装
  • 获取需要接收数据的客户端IP
  • 发送消息
 1     //获取需要发送的消息
 2     string strMsg = txtMsgSend.Text;
 3     //填充数据结构
 4     MessageBase mb = new MessageBase();
 5     mb.UserName = "服务器";                          
 6     mb.MessageType = MessageType.Message;            //消息类型
 7     mb.Messages = Encoding.Default.GetBytes(strMsg); //发送的消息转换为字节数组
 8     mb.FileName = "";                                //发送消息,文件名填空
 9     //获取用户名和用户IP
10     string name=lbOnlineList.SelectedItem.ToString();
11     string ip=server.GetUserID(name);
12     //发送消息
13     if (name != "")
14         server.SendMessage(ip, mb);
15     else
16         MessageBox.Show("错误!");

(3)文件的发送:

  • 获取本地文件路径
  • 通过FileStream读取文件,并将文件保存为byte数组
  • 将消息进行封装
  • 获取需要接收数据的客户端IP
  • 发送消息
 1 //获取文件路径
 2 string filePath = txtSelectFile.Text;
 3 //发送消息
 4 using (FileStream fs = new FileStream(filePath, FileMode.Open))
 5 {
 6     byte[] arrFile = new byte[bufferSize];
 7     int length = fs.Read(arrFile, 0, arrFile.Length);
 8     byte[] arrFileSend = new byte[length];
 9     Array.Copy(arrFile, 0, arrFileSend, 0, length);
10 
11     MessageBase mb = new MessageBase();
12     mb.UserName = "服务器";
13     mb.MessageType = MessageType.File;                //消息类型
14     mb.Messages = arrFileSend;                        //文件转换为字节数组
15     mb.FileName = Path.GetFileName(filePath);         //文件名
16     //获取用户名和用户IP
17     string name = lbOnlineList.SelectedItem.ToString();
18     string ip = server.GetUserID(name);
19     //发送文件
20     if (name != "")
21         server.SendFile(ip, mb);
22     else
23         MessageBox.Show("错误!");
24 }

(4)消息的接收:

  • 获取消息的封装
  • 获取消息并处理数据
1     string strMsg = Encoding.Default.GetString(mb.Messages);
2     Action Update = () =>
3         {
4             txtMsgReceive.Text += string.Format("{0}[{1}]:
{2}
",mb.UserName,DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"),strMsg );                  
5         };
6     //Invoke(Update);           //同步的方法
7     BeginInvoke(Update);        //异步的方法

(5)文件的接收:

  • 另存为对话框提示,获取保存的路径及文件名
  • 提取消息并进行处理
 1 Action Update = () =>
 2         {
 3             //弹出保存对话框
 4             SaveFileDialog sfd = new SaveFileDialog();
 5             sfd.FileName = mb.FileName;
 6             DialogResult dr = sfd.ShowDialog();
 7 
 8             if (dr == DialogResult.OK)
 9             {
10                 //获取文件保存的路径
11                 string fileSavePath = sfd.FileName;
12                 //创建文件流,然后根据路径创建文件
13                 using (FileStream fs = new FileStream(fileSavePath, FileMode.Create))
14                 {
15                     fs.Write(mb.Messages, 0, mb.Messages.Length);
16                     MessageBox.Show("文件保存成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Hand);
17                 }
18             }
19         };
20     Invoke(Update);

(6)有新用户登录:

  • 获取系统中的用户列表
  • 更新用户显示列表
 1     string[] users = server.GetUsers();
 2     Action Update = () =>
 3         {
 4             lbOnlineList.Items.Clear();
 5             for (int i = 0; i < users.Length; i++)
 6             {
 7                 lbOnlineList.Items.Add(users[i]);
 8             }
 9 
10             lbOnlineList.SelectedIndex = 0;
11         };
12     Invoke(Update);

(7)用户退出:

  • 获取系统中的用户列表
  • 更新用户显示列表
 1     string[] users = server.GetUsers();
 2     Action Update = () =>
 3     {
 4         lbOnlineList.Items.Clear();
 5         for (int i = 0; i < users.Length; i++)
 6         {
 7             lbOnlineList.Items.Add(users[i]);
 8         }
 9     };
10     Invoke(Update);

4.客户端功能介绍:

(1)连接服务器:

  • 实例化一个客户端
  • 客户端连接到服务器
  • 订阅客户端的消息接收事件、文件接收事件
1     client = new Client();
2     client.ConnectServer(txtIp.Text, int.Parse(txtPort.Text));
3     //客户端接收到消息
4     client.MessageReceived += client_MessageReceived;
5     //客户端接收到文件
6     client.FileReceived += client_FileReceived;

(2)消息的发送:

  • 获取需要发送的消息
  • 对消息进行封装
  • 向服务器发送消息
 1     //获取需要发送的消息
 2     string strMsg = txtSendMsg.Text;
 3     //填充数据结构
 4     MessageBase mb = new MessageBase();
 5     mb.UserName = txtName.Text;                       //用户名
 6     mb.MessageType = MessageType.Message;             //消息类型
 7     mb.Messages = Encoding.Default.GetBytes(strMsg);  //发送的消息转换为字节数组
 8     mb.FileName = "";                                 //发送消息,文件名填空
 9     //客户端向服务器发送消息
10     client.SendMessage(mb);

(3)文件的发送:

  • 获取本地文件路径
  • 通过FileStream读取文件,并将文件保存为byte数组
  • 将消息进行封装
  • 获取需要接收数据的客户端IP
  • 发送文件
 1 //获取文件路径
 2     string filePath = txtSelectFile.Text;
 3     //发送消息
 4     using (FileStream fs = new FileStream(filePath, FileMode.Open))
 5     {
 6         byte[] arrFile = new byte[bufferSize];
 7         int length = fs.Read(arrFile, 0, arrFile.Length);
 8         byte[] arrFileSend = new byte[length];
 9         Array.Copy(arrFile, 0, arrFileSend, 0, length);
10 
11         MessageBase mb = new MessageBase();
12         mb.UserName = txtName.Text;                   //用户名
13         mb.MessageType = MessageType.File;            //消息类型
14         mb.Messages = arrFileSend;                    //文件转换为字节数组
15         mb.FileName = Path.GetFileName(filePath);     //文件名
16 
17         client.SendFile(mb);
18     }

(4)消息的接收:

  • 获取消息的封装
  • 获取消息并处理数据
1     string strMsg = Encoding.Default.GetString(mb.Messages);
2     Action Update = () =>
3         {
4             txtReceiveMsg.Text += string.Format("{0}[{1}]:
{2}
", mb.UserName, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"), strMsg);   
5         };
6     //Invoke(Update);     //同步
7     BeginInvoke(Update);  //异步

(5)文件的接收:

  • 另存为对话框提示,获取保存的路径及文件名
  • 提取消息并进行处理
 1     Action Update = () =>
 2         {
 3             //弹出保存对话框
 4             SaveFileDialog sfd = new SaveFileDialog();
 5             sfd.FileName = mb.FileName; ;
 6             DialogResult dr = sfd.ShowDialog();
 7 
 8             if (dr == DialogResult.OK)
 9             {
10                 string fileSavePath = sfd.FileName;//获取文件保存的路径
11                 //创建文件流,然后根据路径创建文件
12                 using (FileStream fs = new FileStream(fileSavePath, FileMode.Create))
13                 {
14                     fs.Write(mb.Messages, 0, mb.Messages.Length);
15                     MessageBox.Show("文件保存成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Hand);
16                 }
17             }
18         };
19     Invoke(Update);
原文地址:https://www.cnblogs.com/imstrive/p/6064664.html