C#网络编程之异步模式下的套接字(Socket)服务器和客户端(聊天工具)开发

先看实现效果:
C#网络编程之异步模式下的套接字(Socket)服务器和客户端(聊天工具)开发
代码下载点击这里

异步开发设计思路和同步开发设计思路一样可以简单看下同步开发

异步开发的区别在于,接收信号的方法和发送信息接收信息的方法还有连接的方式采用了异步模式。
接收信号采用 Socket 的BeginAccept()
发数据采用BeginSend()
接收数据采用的BeginReceive()
连接采用的是BeginConnect()
这些方法的具体用法可以自行百度。

下面来看服务器的核心代码。

监听代码:

  try
            {
                //获取IP和端口
                myip = IPAddress.Parse(this.textBox1.Text);
                prot = Int32.Parse(this.textBox2.Text);

                

            }
            catch (Exception)
            {

                MessageBox.Show("您输入的IP地址无效!");
            }
            try
            {
                //实例化主机
                myserver = new IPEndPoint(myip, prot);
                //建立套接字
                mysocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
                //绑定
                mysocket.Bind(myserver);
                //监听
                mysocket.Listen(50);
                this.listBox1.Items.Add("主机"+this.textBox1.Text+"端口"+this.textBox2.Text+"开始监听\r\n");
                //    单独启动线程 等待连接
                Thread thread = new Thread(() =>
                {
                    while (true)
                    {
                        //设为非终止状态      WaitOne将起作用 使线程处于等待状态 
                        myreset.Reset();
                        try
                        {
                            //异步方式等待连接  
                            mysocket.BeginAccept(new AsyncCallback(Acceptacllback), mysocket);
                        }
                        catch (Exception ee)
                        {

                            Console.WriteLine(ee.Message);
                        }
                 

                        //阻塞当前线程,直到收到请求信号
                        myreset.WaitOne();


                    }
                });
                //启动线程
                thread.Start();

            }
            catch (Exception ee)
            {

                Console.WriteLine(ee.Message);
            }

连接上后的回调代码:

 private void Acceptacllback(IAsyncResult ar)
        {
            //将事件终止   WaitOne将不被起作用  线程不会等待
            myreset.Set();
            //获取用户请求的Socket
            Socket listener = ar.AsyncState as Socket;
            try
            {
                //创建新的Socket 处理远程主机通信
                handler = listener.EndAccept(ar);
                //获取状态
                StateObjcet state = new StateObjcet();
                //连接对象的socket
                state.worksocket = handler;
                this.listBox1.Items.Add("与客户建立连接!\r\n");
            }
            catch (Exception ee )
            {

                Console.WriteLine("Socket连接已经断开"); 
            }
            
            //给连接的客户端发通知
            try
            {
                byte[] bytedata = Encoding.BigEndianUnicode.GetBytes("已经建立连接,请开始通话...."+"\r\n");
                //开始发送数据
                handler.BeginSend(bytedata, 0, bytedata.Length, 0, new AsyncCallback((a)=> {
                    try
                    {
                        handler = a.AsyncState as Socket;
                        //结束 并判断是否发送成功!
                        int bytesent = handler.EndSend(a);
                    }
                    catch (Exception eee)
                    {

                        Console.WriteLine(eee.Message);
                     
                    }
          
                   
                }), handler);
            }
            catch (Exception ee)
            {
                Console.WriteLine(ee.Message);
            }


            //开始接收来自客户端的消息
            Thread thread = new Thread(() =>
            {
                try
                {
                    StateObjcet state1 = new StateObjcet();
                    state1.worksocket = handler;
                    handler.BeginReceive(state1.buffer, 0, StateObjcet.buffersize, 0, new AsyncCallback(readcallback), state1);

                }
                catch (Exception)
                {

                    Console.WriteLine("连接中断...");
                }
               

            });
            thread.Start();




        }

读取客户端消息的回调代码:

  private void readcallback(IAsyncResult ar)
        {

            try
            {
                StateObjcet state2 = (StateObjcet)ar.AsyncState;
                Socket tt = state2.worksocket;
                //结束读取并获取读取字节数
                int byteread = handler.EndReceive(ar);
                state2.sb.Append(Encoding.BigEndianUnicode.GetString(state2.buffer, 0, byteread));
                string content = state2.sb.ToString();
                state2.sb.Remove(0, content.Length);
                this.textBox3.AppendText(content + "\r\n");
                //重新开始读取数据
                tt.BeginReceive(state2.buffer, 0, StateObjcet.buffersize, 0, new AsyncCallback(readcallback), state2);
            }
            catch (Exception ee)
            {

                Console.WriteLine("断开连接....");
            }
           

           
        }

发送消息的代码:

 try
            {
                this.textBox3.AppendText("我说:" + this.textBox4.Text + "\r\n");
                byte[] bytaData = Encoding.BigEndianUnicode.GetBytes("服务器说:"+this.textBox4.Text+"\r\n");
                //开始发送
                handler.BeginSend(bytaData, 0, bytaData.Length, 0, new AsyncCallback((a) => {
                    try
                    {
                        handler = a.AsyncState as Socket;
                        //结束 并判断是否发送成功!
                        int bytesent = handler.EndSend(a);
                    }
                    catch (Exception eee)
                    {

                        MessageBox.Show(eee.Message);
                    }


                }), handler);
            }
            catch (Exception ee)
            {

                MessageBox.Show(ee.Message);
            }

停止监听的代码:

try
            {
                mysocket.Close();
                this.listBox1.Items.Add("主机" + this.textBox1.Text + "端口" + this.textBox2.Text + "停止监听.....");

            }
            catch (Exception ee)
            {

                MessageBox.Show(ee.Message);
            }

客户端发送消息接收消息和服务器一样,主要讲一下连接方式:
代码如下:

//获取IP和端口
            try
            {   
                //定义一个存储对象
                IPHostEntry myhost = new IPHostEntry();
                //根据域名或者IP  返回所有关联的地址
                myhost = Dns.GetHostByName(textBox1.Text);
                string IPstring = myhost.AddressList[0].ToString();
                myip = IPAddress.Parse(IPstring);
                //获取端口
                prot = Int32.Parse(this.textBox2.Text);
            }
            catch (Exception)
            {

                MessageBox.Show("您输入的IP地址无效!");
            }
        
            try
            {
                //创建实例
                myserver = new IPEndPoint(myip,prot);
                //创建套接字
                mysocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
                //开始连接
                mysocket.BeginConnect(myserver,new AsyncCallback(Connectcallback),mysocket);
                //等待连接
                connectreaet.WaitOne();


            }
            catch (Exception ee)
            {

                Console.WriteLine("服务器未开启,或关闭");
            }

连接后的回调函数:

    private void Connectcallback(IAsyncResult ar)
        {
            try
            {   //获取服务器的socket信息
                Socket client = (Socket)ar.AsyncState;
                client.EndConnect(ar);
                try
                {
                    byte [] bytedata = Encoding.BigEndianUnicode.GetBytes("连接成功,可以通话...."+"\r\n");
                    mysocket.BeginSend(bytedata, 0, bytedata.Length, 0, new AsyncCallback(SendCallback), mysocket);
                }
                catch (Exception)
                {

                    Console.WriteLine("主机断开连接....");
                }
                this.listBox1.Items.Add("与主机"+this.textBox1.Text+"端口"+this.textBox2.Text+"建立连接!\r\n");
                //接收服务器消息的线程
                Thread thread = new Thread(new ThreadStart(target));
                thread.Start();
                //设置事件终止
                connectreaet.Set();


            }
            catch (Exception)
            {

                Console.WriteLine("主机断开连接....");
            }

        }

本实例还用到了一个封装类
具体代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace 异步套接字客户端开发
{
    class StateObjcet
    {

        public Socket worksocket = null;
        public const int buffersize = 1024;
        public byte[] buffer = new byte[buffersize];
        public StringBuilder sb = new StringBuilder();
    }
}

线程方面主要用到

private static ManualResetEvent sendreset = new ManualResetEvent(false);

ManualResetEvent 介绍

上一篇:基于java的来访咨询系统的设计与实现


下一篇:计算机英文词汇发音