• 局域网之间的通讯实现


    局域网之间通讯有很多种方法,比如可以用数据库存储的方式实现,还可以用udp来实现,这里是用tcp来实现的,用tcp来通讯的话可以说是有点麻烦的,因为要保持各个用户与服务器之间的连接,连接一断便不能通讯了,所以个人觉得这个地方比较麻烦;

    要实现Socket通讯的话首先可以把它分成两个项目来区别,一个是服务器项目(Server),一个是客户端项目(Client)。

    服务器项目的实现可以大致的分成 部分,1:创建一个总连接点,这个连接点负责与客户端的连接,我们不能把连接和通讯都引用到一个连接上,这样服务器会崩溃的,而每个用户都是独立的,所以我们要利用线程来创建一个新的通讯实例,这个连接和通讯各个用户之间都是互不干扰的了,还有一个要注意的就是跨线程调用控件的话是不行的,所以我们又要利用委托存放要调用的功能在用this.Invoke()的方法来跨线程引用控件,接下来就是具体实现响应通讯了;

    客户端相对来说要更容易些,创建一个客户端连接实例,与远程服务器连接起来,然后就是大致的通讯实现功能了。

    下面是我个人的实现代码和实现的心得,附加了大致的注释,实现了群聊,私聊等功能。

    通讯类(Communication)

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Threading.Tasks;
     6 
     7 namespace Server
     8 {
     9     [Serializable]
    10     public class Communication//通讯
    11     {
    12             public string Name { get; set; }
    13             public string Ip { get; set; }//Ip地址
    14         public string Port { get; set; }//端口号
    15         public string Message { get; set; }//发送的消息
    16         public int Types { get; set; }
    17             //1代表聊天信息 2代表客户端人物信息
    18         public bool IsFistLogin { get; set; }
    19             public string ToEndPoint { get; set; }
    20     }
    21 }
    View Code
     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Net.Sockets;
     5 using System.Text;
     6 using System.Threading.Tasks;
     7 
     8 namespace Server
     9 {
    10     [Serializable]
    11     public class ServerReturnInfo
    12     {
    13             public Communication comm { get; set; }//通讯类
    14         public Socket client { get; set; }
    15     }
    16 }
    View Code

    服务器类(Server)

      1 using System;
      2 using System.Collections.Generic;
      3 using System.ComponentModel;
      4 using System.Data;
      5 using System.Drawing;
      6 using System.IO;
      7 using System.Linq;
      8 using System.Net;
      9 using System.Net.Sockets;
     10 using System.Runtime.Serialization.Formatters.Binary;
     11 using System.Text;
     12 using System.Threading;
     13 using System.Threading.Tasks;
     14 using System.Windows.Forms;
     15 
     16 namespace Server
     17 {
     18     public partial class forServer : Form
     19     {
     20         public forServer()
     21         {
     22             InitializeComponent();
     23         }
     24 
     25         private delegate void ListDelegate(Communication comm);
     26         private ListDelegate listInfo = null;//添加成员
     27         private delegate void MessageDelegate(Communication comm);
     28         private MessageDelegate MessageInfo = null;//添加消息
     29         private delegate void SendDelegate(ServerReturnInfo sri);
     30         private SendDelegate SendInfo = null;
     31         private delegate void EndDelegate(Communication commun);
     32         private EndDelegate EndInfo = null;
     33         private List<Socket> socketList = new List<Socket>();//成员集合
     34         private Socket server = null;
     35         private void 开启服务ToolStripMenuItem_Click(object sender, EventArgs e)
     36         {
     37             int port = 0;
     38             server = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
     39             if (!int.TryParse(txtPort.Text, out port))
     40                 port = 8080;
     41             EndPoint endPoint = new IPEndPoint(IPAddress.Any,port);
     42             server.Bind(endPoint);
     43             server.Listen(1000);
     44             rtbMessage.Text = "服务器已经打开!";
     45             Thread t = new Thread(GetClient);
     46             t.Start(server);
     47         }
     48         public void GetClient(object s)//获取客户端实例
     49         {
     50             Socket server = s as Socket;
     51             Socket client = null;
     52             while(true)
     53             {
     54                 try
     55                 {
     56                     client = server.Accept();
     57                 }
     58                 catch (Exception)
     59                 {
     60                     return;
     61                 }
     62                 socketList.Add(client);//把客户端实例添加到集合中
     63                 DisMantle(client);
     64                 Thread t2 = new Thread(ReceiveInfo);
     65                 t2.Start(client);
     66             }
     67         }
     68         //客户端人物信息绑定与上线提醒
     69         public void DisMantle(Socket client)
     70         {
     71             string endPoint = client.RemoteEndPoint.ToString();
     72             string ip = endPoint.Split(':')[0];
     73             string port = endPoint.Split(':')[1];
     74             string name = Dns.GetHostEntry(ip).HostName;
     75             Communication comm = new Communication()
     76             {
     77                 Name = name,
     78                 Ip = ip,
     79                 Port = port,
     80                 Message = name + "上线了!"
     81             };
     82             //通过委托来进行对控件的跨线程修改
     83             //绑定客户端人物信息到ListView控件上
     84             listInfo = new ListDelegate(BindListView);
     85             this.Invoke(listInfo, comm);
     86             //添加聊天消息  
     87             MessageInfo = new MessageDelegate(AddMessage);
     88             this.Invoke(MessageInfo, comm);
     89             ServerReturnInfo sri = new ServerReturnInfo()
     90             {
     91                 comm = comm,
     92                 client = client
     93             };
     94             SendInfo = new SendDelegate(SendInfos);
     95             this.Invoke(SendInfo, sri);
     96         }
     97 
     98         public void SendInfos(object c) //发送列表成员信息到客户端
     99         {
    100             ServerReturnInfo sri = c as ServerReturnInfo;
    101             byte[] b = null;
    102             foreach (Socket s in socketList)
    103             {
    104                 sri.comm.Types = 2;
    105                 sri.comm.IsFistLogin = true;
    106                 for (int i = 0; i < lvInfo.Items.Count; i++)
    107                 {
    108                     sri.comm.Name = lvInfo.Items[i].SubItems[0].Text;
    109                     sri.comm.Ip = lvInfo.Items[i].SubItems[1].Text;
    110                     sri.comm.Port = lvInfo.Items[i].SubItems[2].Text;
    111                     b = SerializeObject(sri.comm);
    112                     s.Send(b);
    113                     sri.comm.IsFistLogin = false;
    114                 }
    115             }
    116         }
    117         public void EndClient(Communication commun) //移除成员列表里离线的成员
    118         {
    119             foreach (ListViewItem items in lvInfo.Items)
    120             {
    121                 //如果成员列表上有此用户,则移除
    122                 if (items.SubItems[0].Text.Equals(commun.Name))
    123                 {
    124                     items.Remove();
    125                     break;
    126                 }
    127             }
    128         }
    129         public void ReceiveInfo(object o) //获取客户端信息
    130         {
    131             Socket client = o as Socket;
    132             byte[] b = new byte[1024];
    133             Communication commun = null;
    134             while (true)
    135             {
    136                 try
    137                 {
    138                     client.Receive(b);
    139                     commun = DeserializeObject(b) as Communication;
    140                 }
    141                 catch (Exception)
    142                 {
    143                     
    144                     return;
    145                 }
    146                 if (commun.Types == 1)//客户端发送过来的信息
    147                 {
    148                     MessageInfo = new MessageDelegate(AddMessage);
    149                     this.Invoke(MessageInfo, commun);
    150                     byte[] bb = SerializeObject(commun);
    151                     foreach (Socket c in socketList)
    152                     {
    153                         c.Send(bb);//把客户端的消息发送到其它的客户端
    154                     }
    155                 }
    156                 else if (commun.Types == 3) //私聊,判断终结点是否一致
    157                 {
    158                     MessageInfo = new MessageDelegate(AddMessage);
    159                     this.Invoke(MessageInfo, commun);
    160                     byte[] bb = SerializeObject(commun);
    161                     foreach (Socket c in socketList)
    162                     {
    163                         string ClientEndPoint = c.RemoteEndPoint.ToString();
    164                         if (commun.ToEndPoint.Equals(ClientEndPoint))
    165                         {
    166                             c.Send(bb);
    167                             break;
    168                         }
    169                     }
    170                 }else if(commun.Types == 4)
    171                 {
    172                     MessageInfo = new MessageDelegate(AddMessage);
    173                     this.Invoke(MessageInfo, commun);
    174                     byte[] bb = SerializeObject(commun);
    175                     try
    176                     {
    177                         foreach (Socket c in socketList)
    178                         {
    179                             if (c.Connected)
    180                                 c.Send(bb);//把客户端的离线消息发送到其它的客户端
    181                         }
    182                     }
    183                     catch (Exception)
    184                     {
    185                         socketList.Remove(client);//从集合中删除该用户
    186                         EndInfo = new EndDelegate(EndClient);
    187                         this.Invoke(EndInfo, commun);
    188                         client.Dispose();//关闭端口
    189                         return;
    190                     }
    191                 }
    192             }
    193         }
    194         public void ClearList() 
    195         {
    196             lvInfo.Items.Clear();//清除ListView控件上的数据
    197         }
    198         public void BindListView(Communication comm) //绑定客户端人物信息到ListView控件上
    199         {
    200             ListViewItem items = new ListViewItem(comm.Name);
    201             items.SubItems.Add(comm.Ip);
    202             items.SubItems.Add(comm.Port);
    203             lvInfo.Items.Add(items);
    204         }
    205         public void AddMessage(Communication comm)//添加聊天消息
    206         {
    207             rtbMessage.Text += "
    "+comm.Name + ":" + comm.Message;
    208         }
    209 
    210         public object DeserializeObject(byte[] pBytes)//反序列化二进制为对象
    211         {
    212             object newOjb = null;
    213             if (pBytes == null)
    214                 return newOjb;
    215             MemoryStream memory = new MemoryStream(pBytes);
    216             memory.Position = 0;
    217             BinaryFormatter formatter = new BinaryFormatter();
    218             newOjb = formatter.Deserialize(memory);
    219             memory.Close();
    220             return newOjb;
    221         }
    222         public byte[] SerializeObject(object pObj)//序列化对象为二进制的数
    223         {
    224             if (pObj == null)
    225                 return null;
    226             MemoryStream memory = new MemoryStream();
    227             BinaryFormatter formatter = new BinaryFormatter();
    228             formatter.Serialize(memory, pObj);
    229             memory.Position = 0;
    230             byte[] read = new byte[memory.Length];
    231             memory.Read(read, 0, read.Length);
    232             memory.Close();
    233             return read;
    234         }
    235 
    236         private void 退出程序ToolStripMenuItem_Click(object sender, EventArgs e)
    237         {
    238             Application.Exit();
    239         }
    240 
    241         private void forServer_FormClosing(object sender, FormClosingEventArgs e)
    242         {
    243             //检查服务是否还在工作 
    244         }
    245 
    246         private void forServer_Load(object sender, EventArgs e)
    247         {
    248             txtPort.Text = "8080";
    249         }
    250     }
    251 }
    View Code

    客户端类(Client)

      1 using System;
      2 using System.Collections.Generic;
      3 using System.ComponentModel;
      4 using System.Data;
      5 using System.Drawing;
      6 using System.IO;
      7 using System.Linq;
      8 using System.Net;
      9 using System.Net.Sockets;
     10 using System.Runtime.Serialization.Formatters.Binary;
     11 using System.Text;
     12 using System.Threading;
     13 using System.Threading.Tasks;
     14 using System.Windows.Forms;
     15 using Server;
     16 
     17 namespace Client
     18 {
     19     public partial class forClient : Form
     20     {
     21         public forClient()
     22         {
     23             InitializeComponent();
     24         }
     25 
     26         private delegate void ListDelegate(Communication comm);
     27         private ListDelegate listInfo = null;//用于绑定成员
     28         private delegate void MessageDelegate(Communication comm);
     29         private MessageDelegate MessageInfo = null;//用于添加聊天消息
     30         private delegate void ClearDelegate();
     31         private ClearDelegate ClearInfo = null;//用于清除成员列表
     32         private delegate void EndDelegate(Communication commun);
     33         private EndDelegate EndInfo = null;
     34         Socket client = null;
     35         EndPoint endPoint = null;
     36         private void 开启服务ToolStripMenuItem_Click(object sender, EventArgs e)
     37         {
     38             int port = 0;
     39             client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
     40             if (!int.TryParse(txtPort.Text, out port))
     41                 port = 8080;
     42             endPoint = new IPEndPoint(IPAddress.Parse(txtIP.Text), port);
     43             client.Connect(endPoint);
     44             rtbMessage.Text = "连接服务器成功!";
     45             Thread t = new Thread(ReceiveInfo);
     46             t.Start(client);
     47         }
     48         public void ClearList() //清除成员列表
     49         {
     50             this.lvInfo.Clear();
     51         }
     52         public void EndClient(Communication commun) //移除成员列表里离线的成员
     53         {
     54             foreach (ListViewItem items in lvInfo.Items)
     55             {
     56                 //如果成员列表上有此用户,则移除
     57                 if (items.SubItems[0].Text.Equals(commun.Name))
     58                 {
     59                     items.Remove();
     60                     break;
     61                 }
     62             }
     63         }
     64         public void ReceiveInfo(object c)//接收服务器的信息
     65         {
     66             byte[] b = new byte[1024];
     67             Socket client = c as Socket;
     68             ClearInfo = new ClearDelegate(ClearList);
     69             while(true)
     70             {
     71                 try
     72                 {
     73                     client.Receive(b);
     74                 }
     75                 catch (Exception)
     76                 {
     77                     client.Dispose();
     78                     return;
     79                 }
     80                 Communication comm = DeserializeObject(b) as Communication;
     81                 if (comm.Types == 2)//服务器回发过来的信息
     82                 {
     83                     listInfo = new ListDelegate(BindListView);
     84                     this.Invoke(listInfo, comm);
     85                 }
     86                 else if (comm.Types == 1 || comm.Types == 3)
     87                 {
     88                     MessageInfo = new MessageDelegate(AddMessage);
     89                     this.Invoke(MessageInfo, comm);
     90                 }
     91                 else //下线执行
     92                 {
     93                     MessageInfo = new MessageDelegate(AddMessage);
     94                     this.Invoke(MessageInfo, comm);
     95                     EndInfo = new EndDelegate(EndClient);
     96                     this.Invoke(EndInfo,comm);
     97                 }
     98             }
     99         }
    100         public void BindListView(Communication comm) //绑定客户端人物信息到ListView控件上
    101         {
    102             if(comm.IsFistLogin)
    103             {
    104                 lvInfo.Items.Clear();//第一次添加的时候(判定为true时)清除原有的旧成员
    105             }
    106             ListViewItem items = new ListViewItem(comm.Name);
    107             items.SubItems.Add(comm.Ip);
    108             items.SubItems.Add(comm.Port);
    109             lvInfo.Items.Add(items);
    110         }
    111         public void AddMessage(Communication comm)//添加聊天消息
    112         {
    113             rtbMessage.Text += "
    "+comm.Name + ":" + comm.Message;
    114         }
    115         public object DeserializeObject(byte[] pBytes)//反序列化二进制为对象
    116         {
    117             object newOjb = null;
    118             if (pBytes == null)
    119                 return newOjb;
    120             MemoryStream memory = new MemoryStream(pBytes);
    121             memory.Position = 0;
    122             BinaryFormatter formatter = new BinaryFormatter();
    123             newOjb = formatter.Deserialize(memory);
    124             memory.Close();
    125             return newOjb;
    126         }
    127         public byte[] SerializeObject(object pObj)//序列化对象为二进制的数
    128         {
    129             if (pObj == null)
    130                 return null;
    131             MemoryStream memory = new MemoryStream();
    132             BinaryFormatter formatter = new BinaryFormatter();
    133             formatter.Serialize(memory, pObj);
    134             memory.Position = 0;
    135             byte[] read = new byte[memory.Length];
    136             memory.Read(read, 0, read.Length);
    137             memory.Close();
    138             return read;
    139         }
    140 
    141         private void btnSend_Click(object sender, EventArgs e)
    142         {
    143             Communication comm = new Communication() {
    144                 Name = Dns.GetHostName(),
    145                 Message = txtMessage.Text,
    146                 Types = 1
    147             };
    148             if (lvInfo.SelectedItems.Count > 0)//私聊
    149             {
    150                 comm.Types = 3;
    151                 string ePoint = lvInfo.SelectedItems[0].SubItems[1].Text +":"+ lvInfo.SelectedItems[0].SubItems[2].Text;
    152                 comm.ToEndPoint = ePoint;
    153             }
    154             byte[] b = SerializeObject(comm);
    155             client.Send(b);
    156             lvInfo.SelectedItems.Clear();//清除选中的个数
    157         }
    158 
    159         private void 退出程序ToolStripMenuItem_Click(object sender, EventArgs e)
    160         {
    161             Communication comm = new Communication()
    162             {
    163                 Name = Dns.GetHostName(),
    164                 Message = "下线了!",
    165                 Types = 4//用户下线类型
    166             };
    167             byte[] b = SerializeObject(comm);
    168             client.Send(b);
    169             client.Dispose();
    170             Application.Exit();
    171         }
    172 
    173         private void forClient_Load(object sender, EventArgs e)
    174         {
    175             //127.0.0.1 用于获取本机IP
    176             txtIP.Text = "192.168.1.100";
    177             txtPort.Text = "8080";
    178         }
    179     }
    180 }
    View Code
  • 相关阅读:
    在android模拟器运行arm 移植的 c程序
    Android实现对c++方式调用
    Hdu 1003 Max Sum
    HDU 1005 Number Sequence
    poj 1222 EXTENDED LIGHTS OUT 高斯消元法
    分治算法
    HDU杭电acm题目分类大全
    HDU 1002 A + B Problem II 大数相加
    HDU 1004 Let the Balloon Rise
    phpcms栏目和专题的区分
  • 原文地址:https://www.cnblogs.com/LiuZhen/p/3489644.html
Copyright © 2020-2023  润新知