c# 网络通信

来源:互联网 发布:淘宝开企业店铺费用 编辑:程序博客网 时间:2024/04/27 07:23

                                                                                              c# 服务器端网络通信  

  最近的工作涉及到网络通信,在此小结一下这段时间的收获和遇到的问题。

  一.通信方式:

  1. Server/Client:

       Server:Client : 

      1        :      1

      1        :      n(并发服务器方式)

      n        :      1(电驴,工控软件 ,额~我们的项目做客户端界面,也是如此的架构,不过目前只是1对1的,n对1需要创建多个连接,目前还没做难过)

  2.连接方式

     长连接

     短连接

 3.发送接收数据方式

    异步

    异步双工:接收和发送都在同一个程序中,有两个不同的子进程分别负责发送和接收。

    异步单工:接收和发送是用两个不同的程序。

    同步

    报文发送后等待接收。同步通讯时,要考虑到超时。

  下面贴一些最近学习网络编程时写的一些程序,我是用Socket调试工具调试完成了,不过还需要很多的改进。

   Part .1 同步通信

   

  public  class SyncServer    {        public delegate void ActionMsgDelegate(object sender, ActionMsgEventArgs args);        public event ActionMsgDelegate ActionMsgEvent;        private IPAddress myIP= IPAddress.Parse("127.0.0.1");        private int myPort = 8000;        private IPEndPoint myServer;        private Socket socket;        private bool check = true;        private Socket acceptSocket;        public static bool SocketServiceFlag = true;        public SyncServer( string ip,int port )        {            myIP = IPAddress.Parse(ip);            myPort = port;        }        public void Accept( )        {            myServer = new IPEndPoint(myIP, myPort);            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);            Thread thread = new Thread(new ThreadStart( Receive));            thread.Start();        }        public void Receive()        {            try            {                socket.Bind(myServer);                socket.Listen(50);                while (SocketServiceFlag)                {                    acceptSocket = socket.Accept();                    if (acceptSocket.Connected)                    {                        Thread thread = new Thread(new ThreadStart(Round));                        thread.IsBackground = true;                        thread.Start();                    }                    Thread.Sleep(1000);                }            }            catch (Exception ex)            {            }        }        public void Round()        {               while( true )              {                  try                  {                      if (!acceptSocket.Connected||!check)                      {                          break;                      }                      Byte[] Rec = ReadData();                      ///输出数据                      if(Rec!=null)                      {                          string RecMessage = System.Text.Encoding.Default.GetString(Rec,0,Rec.Length);                          updateUI("接收数据:" + RecMessage);                          if (!check)                          {                              break;                          }                          string SendMessage = "返回数据:" + RecMessage;                          updateUI(SendMessage);                          byte[] sendByte = System.Text.Encoding.Default.GetBytes(SendMessage.ToCharArray());                          SendData(sendByte);                          if (!check)                          {                              break;                          }                      }                      if (!check)                      {                          break;                      }                  }                  catch                   {                  }              }        }        public Byte[]  ReadData(  )        {            Byte[] Rec = new Byte[64];           int len = 0;           try           {               if (!acceptSocket.Connected||!SocketServiceFlag)               {                   check = false;                   return Rec;               }               NetworkStream netStream = new NetworkStream(acceptSocket);               len=netStream.Read(Rec, 0, Rec.Length);               Array.Resize( ref Rec, len);//重新调整RecBuffer的大小           }           catch(SocketException ex)           {               if(len==0)                {                  MessageBox.Show("连接断开");                  check = false;               }           }           if (len > 0)           {               return Rec;           }           return null;        }        public void SendData( Byte[] sendByte )        {            try            {                if (!acceptSocket.Connected||!SocketServiceFlag)                {                    check = false;                    return;                }                NetworkStream netStream = new NetworkStream(acceptSocket);                netStream.WriteTimeout = 200;                netStream.Write(sendByte, 0, sendByte.Length);            }catch(Exception ex)            {                MessageBox.Show("发送数据有误:"+ex.Message);                check = false;            }        }        public void Close()        {            try            {                SocketServiceFlag = false;                check = false;                socket.Close();            }            catch(Exception ex)            {                MessageBox.Show("关闭连接有误:"+ex.Message);            }        }        public void updateUI( string message )        {            ActionMsgEvent(this, new ActionMsgEventArgs("(" + DateTime.Now.ToLocalTime().ToString() + "):" + message + "\r\n"));        }        public void OnActionMsg(ActionMsgEventArgs args)        {            if (ActionMsgEvent != null)            {                ActionMsgEvent(this, args);            }        }    }
Part.2 使用TcpListener进行同步通信

    public class TServer    {        public delegate void ActionMsgDelegate(object sender, ActionMsgEventArgs args);        public event ActionMsgDelegate ActionMsgEvent;        private int port = 8000;        private TcpListener listener = null;        private Socket mySocket = null;        private NetworkStream netStream = null;        private bool SocketServerFlag = true;        public TServer( int port )        {            this.port = port;        }        /// <summary>        /// 启动监听        /// </summary>        public void Accept( )        {            listener = new TcpListener(port);//参数为端口号            listener.Start();            Thread thread = new Thread(new ThreadStart( Recieve));            thread.Start();        }        /// <summary>        /// 接收数据        /// </summary>        public void Recieve( )        {            try            {                while (SocketServerFlag)                {                    if (listener.Pending())                    {                        mySocket = listener.AcceptSocket();                        if (mySocket.Connected)                        {                            Thread thread = new Thread(new ThreadStart(Round));                            thread.Start();                        }                    }                    Thread.Sleep(1000);                }            }catch(Exception ex)            {                MessageBox.Show(ex.Message );            }        }        /// <summary>        /// 接收并发送数据        /// </summary>        public void Round()        {            while (true)            {                Byte[] Rec = ReadData();                if( Rec!=null)                {                   string RecMessage = System.Text.Encoding.Default.GetString(Rec);                   updateUI("接收数据:" + RecMessage);                   string SendMessage = "返回数据:" + RecMessage;                   updateUI(SendMessage);   //界面显示                   byte[] sendByte = System.Text.Encoding.Default.GetBytes(SendMessage.ToCharArray());                   SendData(sendByte);                }            }        }        /// <summary>        /// 读取数据局        /// </summary>        /// <returns></returns>        public Byte[] ReadData()        {            Byte[] Rec = new Byte[64];            int len = 0;            try            {                if (!mySocket.Connected||!SocketServerFlag)                {                    return Rec;                }                NetworkStream netStream = new NetworkStream(mySocket);                len = netStream.Read(Rec, 0, Rec.Length);                Array.Resize(ref Rec, len);//重新调整RecBuffer的大小                //string RecMessage = System.Text.Encoding.Default.GetString(Rec,0,len);//去除多余的\0数据            }            catch (SocketException ex)            {                if (len == 0)                {                    MessageBox.Show("连接断开");                }            }            if (len > 0)            {                return Rec;            }            return null;        }        /// <summary>        /// 发送数据        /// </summary>        /// <param name="messageByte"></param>        public void SendData(byte[] messageByte)        {            try            {                if( mySocket.Connected && SocketServerFlag)                {                    netStream = new NetworkStream(mySocket);                    netStream.Write(messageByte, 0, messageByte.Length);                    netStream.Flush();                }            }            catch (Exception ex)            {            }        }        /// <summary>        /// 关闭连接        /// </summary>        public void Close()        {            try            {                SocketServerFlag = false;                mySocket.Close();                listener.Stop();            }            catch(Exception ex)            {                MessageBox.Show("关闭连接异常");            }        }        /// <summary>        /// 更新界面        /// </summary>        /// <param name="message"></param>        public void updateUI(string message)        {            ActionMsgEvent(this, new ActionMsgEventArgs("(" + DateTime.Now.ToLocalTime().ToString() + "):" + message + "\r\n"));        }        public void OnActionMsg(ActionMsgEventArgs args)        {            if (ActionMsgEvent != null)            {                ActionMsgEvent(this, args);            }        }    }

Part .3 简单异步通信


using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Net;using System.Net.Sockets;using System.Threading;using System.Windows.Forms;namespace ServerWork.Server{    public class StateObject    {        public Socket workSocket = null;        public const int BufferSize = 1024;        public byte[] buffer = new byte[BufferSize];        public StringBuilder sb = new StringBuilder();        public StateObject()        {        }    }    public class AsyncServer    {        public delegate void ActionMsgDelegate(object sender, ActionMsgEventArgs args);        public event ActionMsgDelegate ActionMsgEvent;        private IPAddress myIP = null;        private int port = 8000;        private IPEndPoint myServer;        private Socket mySocket;        private Socket handler;        private static ManualResetEvent myReset = new ManualResetEvent(false);//ManualResetEvent建立时是把false作为start的初始状态,这个类用于通知另一个线程,让它等待一个或多个线程。        public bool SocketServerFlag = true;        public bool blQuitListened = false;        public AsyncServer( int port)        {            this.port = port;        }        public void Accept()        {            try            {                string strIP = getIPAddress();                myIP = IPAddress.Parse(strIP);                myServer = new IPEndPoint(myIP, port);                mySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);                mySocket.Bind(myServer);                mySocket.Listen(50);                Thread thread = new Thread(new ThreadStart(target));                thread.Start();            }catch(Exception ex)            {                MessageBox.Show(ex.Message);            }        }        private string getIPAddress( )        {            // 获得本机局域网IP地址            IPAddress[] AddressList = Dns.GetHostByName(Dns.GetHostName()).AddressList;            if (AddressList.Length < 1)            {                return "";            }            return AddressList[0].ToString();        }         public void target()        {            while (!blQuitListened)            {                myReset.Reset();                mySocket.BeginAccept(new AsyncCallback(AcceptCallback), mySocket);                myReset.WaitOne();//阻塞当前线程,知道收到请求信号            }        }        public void AcceptCallback(IAsyncResult ar)        {            myReset.Set();//将事件设为终止            Socket listener = (Socket)ar.AsyncState;            if(blQuitListened)            {                SocketServerFlag = false;                return;            }            handler = listener.EndAccept(ar);            StateObject state = new StateObject();//获取状态            state.workSocket = handler;//与客户建立连接            SocketServerFlag = true;            byte[] sendBuffer = System.Text.Encoding.Default.GetBytes("已经准备好监听");            SendData(sendBuffer );            Thread thread = new Thread(new ThreadStart(beginReceive)); //开启线程接收数据            thread.Start();        }        public void SendData(byte[] sendData)        {            try            {                if( !handler.Connected||!SocketServerFlag)                {                    return;                }                handler.BeginSend(sendData, 0, sendData.Length, 0, new AsyncCallback(SendCallback), handler);            }catch( Exception ex)            {                MessageBox.Show(ex.Message);            }        }        public void SendCallback(IAsyncResult ar)        {            try            {                handler = (Socket)ar.AsyncState;                int bytesSent = handler.EndSend(ar);            }            catch (Exception ex)            {                MessageBox.Show(ex.Message);            }        }        public void beginReceive( )        {            try            {                StateObject state = new StateObject();                state.workSocket = handler;                handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);            }            catch (Exception ex)            {                MessageBox.Show("开始接收数据异常");                SocketServerFlag = false;            }        }        public void ReadCallback(IAsyncResult ar)        {            try            {                StateObject state = (StateObject)ar.AsyncState;                Socket tt = state.workSocket;                if (!tt.Connected|| !SocketServerFlag)                {                    return;                }                int bytesRead = handler.EndReceive(ar);//结束读取并获取字节数                if( bytesRead<1)                {                    SocketServerFlag = false;                    return;                }                state.sb.Append(System.Text.Encoding.Default.GetString(state.buffer, 0, bytesRead));                string content = state.sb.ToString();                updateUI("接收数据:"+content );                state.sb.Remove(0, content.Length);//清除state.sb内容,准备重新复制                tt.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);            }            catch (Exception ex)            {                MessageBox.Show("读取数据异常");                SocketServerFlag = false;            }        }        public void updateUI(string message)        {            ActionMsgEvent(this, new ActionMsgEventArgs("(" + DateTime.Now.ToLocalTime().ToString() + "):" + message + "\r\n"));        }        public void OnActionMsg(ActionMsgEventArgs args)        {            if (ActionMsgEvent != null)            {                ActionMsgEvent(this, args);            }        }        public void Close()        {            try            {                mySocket.Close();            }            catch            {                MessageBox.Show("关闭网络连接异常");            }        }    }}
上面程序中需要将一些发送接收的数据传递显示到界面上,所以有用到自定义的委托。

附winform中界面以及简单调用程序:



namespace ServerWork{    public partial class ServerForm : Form    {        public delegate void SetTextCallback(string text );        private SyncServer Server = null;        private TServer tServer = null;        private AsyncServer aServer = null;        public ServerForm()        {            InitializeComponent();        }        private void rtbShow_TextChanged(object sender, EventArgs e)        {            rtbShow.SelectionStart = rtbShow.Text.Length;//实现自动滚动显示追加内容            rtbShow.SelectionLength = 0;            rtbShow.Focus();        }        private void btnStart_Click(object sender, EventArgs e)        {            try            {                string strIPAddress = tbIPAddress.Text.Trim();                string strPort = tbPort.Text.Trim();                //Server = new SyncServer(strIPAddress, int.Parse(strPort));                //Server.ActionMsgEvent += new SyncServer.ActionMsgDelegate(UpdateRichText);                //Server.Accept( );                //tServer = new TServer( int.Parse(strPort));                //tServer.ActionMsgEvent +=new TServer.ActionMsgDelegate(UpdateRichText);                //tServer.Accept();                aServer = new AsyncServer(int.Parse(strPort));                aServer.ActionMsgEvent +=new AsyncServer.ActionMsgDelegate(UpdateRichText);                aServer.Accept();            }catch(Exception ex)            {                MessageBox.Show("监听异常!");            }        }        private void btnSend_Click(object sender, EventArgs e)        {            //if(Server!=null&&Server.SocketServerFlag )            //{            //    string sendData = rtbSend.Text;            //    byte[] buffer = System.Text.Encoding.Default.GetBytes(sendData);            //    Server.SendData( buffer );            //    rtbShow.AppendText("(" + DateTime.Now.ToLocalTime().ToString() + "):" + sendData + "\r\n");            //}            //if (tServer != null&&tServer.SocketServerFlag)            //{            //    string sendData = rtbSend.Text;            //    byte[] buffer = System.Text.Encoding.Default.GetBytes(sendData);            //    tServer.SendData(buffer);            //    rtbShow.AppendText("(" + DateTime.Now.ToLocalTime().ToString() + "):" + sendData + "\r\n");            //}            if (aServer != null && aServer.SocketServerFlag)            {                string sendData = rtbSend.Text;                byte[] buffer = System.Text.Encoding.Default.GetBytes(sendData);                aServer.SendData(buffer);                rtbShow.AppendText("(" + DateTime.Now.ToLocalTime().ToString() + "):发送数据:" + sendData + "\r\n");            }        }        private void btnStop_Click(object sender, EventArgs e)        {            try            {                //Server.Close();//关闭连接               // tServer.Close();                aServer.blQuitListened = true;                aServer.Close();            }catch( Exception ex)            {                MessageBox.Show("关闭连接异常");            }        }        public void SetText(string text )        {            if (this.rtbShow.InvokeRequired)            {                SetTextCallback d = new SetTextCallback(SetText);                this.BeginInvoke(d, new object[] { text });            }            else            {                this.rtbShow.AppendText(text);                this.rtbShow.Refresh();            }        }        public void UpdateRichText(object sender, ActionMsgEventArgs e)        {            this.BeginInvoke((EventHandler)(delegate            {                rtbShow.AppendText(e.Message + "\r\n");//在richTextBox中追加内容            }));        }    }}
在此做一小结,其实上面的服务器端程序写的还不完善,实际的工作中可能会需要很多复杂的情况。

比如,服务器端如何判断客户端关闭了连接;

客户端报文分发;(上面的程序中没有提到)

服务器端最多可连接多少个客户端并保持并发稳定性;

双向通信控制;

通信协议制度以及拆分拼包处理;(微笑在写客户端程序时,我就遇到了此类问题)

数据接收到后是否有缓存机制;

如何快速找到要发送信息的客户端地址等问题都需要一一解决。

如果您有更好的建议,可以多多交流,互相学习。



  


0 0
原创粉丝点击