zoukankan      html  css  js  c++  java
  • 基于socket实现的简单的聊天程序

      记得八年前第一次使用socket做的一个五子棋程序,需要序列化棋子对象,传递到对方的电脑上。 一个偶然的机会,第二次使用socket做点事情。先看聊天服务器端的实现:

         服务器端要实现以下功能:

         1、启动服务,开启监听

         2、持续不断地接收消息

         3、发送消息

        启动服务,创建监听socket,绑定Ip和端口:

     1         /// <summary>
     2         /// 启动服务
     3         /// </summary>
     4         private void Start()
     5         {
     6             socketwatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
     7 
     8             IPAddress address = IPAddress.Parse("10.0.0.31");
     9 
    10             IPEndPoint point = new IPEndPoint(address, 8025);
    11 
    12             socketwatch.Bind(point);
    13 
    14             //将套接字的监听队列长度限制为20  
    15             socketwatch.Listen(20);
    16 
    17             //创建一个监听线程  
    18             threadwatch = new Thread(watchconnecting);
    19 
    20             threadwatch.IsBackground = true;
    21 
    22             threadwatch.Start();
    23         }

    创建接收数据的Socket:

     1  //监听客户端发来的请求  
     2         private void watchconnecting()
     3         {
     4             Socket connection = null;
     5             while (true)  //持续不断监听客户端发来的请求     
     6             {
     7                 try
     8                 {
     9                     connection = socketwatch.Accept();
    10                 }
    11                 catch (Exception ex)
    12                 {
    13                     MessageBox.Show(ex.Message); //提示套接字监听异常     
    14                     break;
    15                 }
    16                 //获取客户端的IP和端口号  
    17                 IPAddress clientIP = (connection.RemoteEndPoint as IPEndPoint).Address;
    18                 int clientPort = (connection.RemoteEndPoint as IPEndPoint).Port;
    19 
    20                 //让客户显示"连接成功的"的信息  
    21                 string sendmsg = "连接服务端成功!
    " + "本地IP:" + clientIP + ",本地端口" + clientPort.ToString();
    22                 byte[] arrSendMsg = Encoding.UTF8.GetBytes(sendmsg);
    23                 connection.Send(arrSendMsg);
    24 
    25                 RemoteEndPoint = connection.RemoteEndPoint.ToString(); //客户端网络结点号  
    26                 dic.Add(RemoteEndPoint, connection);    //添加客户端信息  
    27 
    28                 IPEndPoint netpoint = connection.RemoteEndPoint as IPEndPoint;
    29 
    30                 //创建一个通信线程      
    31                 ParameterizedThreadStart pts = new ParameterizedThreadStart(recv);
    32                 Thread thread = new Thread(pts);
    33                 thread.IsBackground = true;//设置为后台线程,随着主线程退出而退出     
    34                 //启动线程     
    35                 thread.Start(connection);
    36             }
    37         }

    socketwatch.Accept()
    会创建一个新的socket,它用来负责和某个客户端的通讯。

    接收数据:
     1         private void recv(object socketclientpara)
     2         {
     3 
     4             Socket socketServer = socketclientpara as Socket;
     5             while (true)
     6             {
     7                 byte[] arrServerRecMsg = new byte[1024 * 1024];
     8                 try
     9                 {
    10                     int length = socketServer.Receive(arrServerRecMsg);
    11 
    12                     string strSRecMsg = Encoding.UTF8.GetString(arrServerRecMsg, 0, length);
    13 
    14                     this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
    15                               (ThreadStart)delegate()
    16                               {
    17                                   MessagePool.Insert(MessagePool.Count, new Message() { MessageInfo = strSRecMsg, IdentityName = socketServer.RemoteEndPoint.ToString() });
    18                               });
    19                 }
    20                 catch (Exception ex)
    21                 {
    22                     MessageBox.Show(ex.Message);
    23                     socketServer.Close();
    24                     break;
    25                 }
    26             }
    27         }

    把从客户端接收过来的字节流变为字符串,然后添加到页面上。

    发送消息:

     1         private static object lockPool = new object();
     2         public static ObservableCollection<Message> MessagePool = new ObservableCollection<Message>();
     3         private void send_Click(object sender, RoutedEventArgs e)
     4         {
     5             string msg = this.message.Text;
     6 
     7             this.message.Clear();
     8 
     9             lock (lockPool)
    10             {
    11                 MessagePool.Insert(MessagePool.Count, new Message() { MessageInfo = msg, IdentityName = "wbq" });
    12             }
    13 
    14             string sendMsg = msg; 
    15             byte[] bytes = System.Text.Encoding.UTF8.GetBytes(sendMsg);
    16 
    17             if (dic.Count > 0)
    18                 dic.First().Value.Send(bytes);
    19         }
    dic.First().Value.Send,从字典中获取到之前创建好的通讯socket,然后调用send方法。

    客户端需要实现以下功能:
    1、和服务器建立连接
    2、接收数据
    3、发送数据

    建立连接:
     1    private void Start()
     2         {
     3 
     4             //定义一个套接字监听  
     5             socketclient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
     6 
     7 
     8            var servers= GetServers();
     9 
    10 
    11            if (servers.Count > 0)
    12            {
    13 
    14                //获取文本框中的IP地址  
    15                IPAddress address = IPAddress.Parse(servers.First().IPToPing);
    16 
    17                //将获取的IP地址和端口号绑定在网络节点上  
    18                IPEndPoint point = new IPEndPoint(address, int.Parse(servers.First().Port));
    19 
    20                try
    21                {
    22                    //客户端套接字连接到网络节点上,用的是Connect  
    23                    socketclient.Connect(point);
    24                }
    25                catch (Exception)
    26                {
    27                    //MessageBox.  
    28                    MessageBox.Show("连接失败
    ");
    29                    return;
    30                }
    31 
    32                threadclient = new Thread(recv);
    33 
    34                threadclient.IsBackground = true;
    35 
    36                threadclient.Start();
    37            }
    38         }

    接收消息:

     1        // 接收服务端发来信息的方法    
     2         private void recv()//  
     3         {
     4             while (true)//持续监听服务端发来的消息  
     5             {
     6                 try
     7                 {
     8                     //定义一个1M的内存缓冲区,用于临时性存储接收到的消息  
     9                     byte[] arrRecvmsg = new byte[1024 * 1024];
    10 
    11                     //将客户端套接字接收到的数据存入内存缓冲区,并获取长度  
    12                     int length = socketclient.Receive(arrRecvmsg);
    13 
    14                     //将套接字获取到的字符数组转换为人可以看懂的字符串  
    15                     string strRevMsg = Encoding.UTF8.GetString(arrRecvmsg, 0, length);
    16 
    17                     this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
    18                                (ThreadStart)delegate()
    19                                {
    20                                    MessagePool.Insert(MessagePool.Count, new Message() { MessageInfo = strRevMsg, IdentityName = socketclient.RemoteEndPoint.ToString() });
    21                                });
    22                 }
    23                 catch (Exception ex)
    24                 {
    25                     MessageBox.Show("远程服务器已经中断连接" + ex.Message);
    26                     break;
    27                 }
    28             }
    29         }
    发送消息:
     1         private void send_Click(object sender, RoutedEventArgs e)
     2         {
     3             string strRevMsg = this.message.Text;
     4             this.message.Clear();
     5 
     6             lock (lockPool)
     7             {
     8                 MessagePool.Insert(MessagePool.Count, new Message() { MessageInfo = strRevMsg, IdentityName = "我(" + socketclient.LocalEndPoint.ToString() + ")" });
     9             }
    10 
    11             //将输入的内容字符串转换为机器可以识别的字节数组     
    12             byte[] arrClientSendMsg = Encoding.UTF8.GetBytes(strRevMsg);
    13             //调用客户端套接字发送字节数组     
    14             socketclient.Send(arrClientSendMsg);
    15         }
    经过和同事的测试,可以实现简单的文字聊天,此代码仅为测试代码,若要用于实际的项目中,需要很大改进,比如socket异步建立,消息接收和发送等等。











  • 相关阅读:
    理解Linq和lambda
    (转)Fidder教程
    (转)Fiddler Composer创建和发送HTTP Request
    (转)http协议详解
    C# sealed & internal
    javascript中的封装,多态,继承
    Fiddler Script 用法
    强烈推荐:240多个jQuery插件
    用C#编写ActiveX控件(1)
    用C#编写ActiveX控件(二)
  • 原文地址:https://www.cnblogs.com/wangqiang3311/p/7145066.html
Copyright © 2011-2022 走看看