Socket同步异步学习

    那么进入本文的正题。Socket编程时网络编程的基础,C#的NET库封装了网络通信的诸多API,简要介绍几个常用的函数: 
     1.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 网络套接字的类。其中第一个参数表示支持的ip协议类型,这里选择支持ipv4,也可选择支持ipV6,第二个参数表示是基于数据流的,第三个参数是socket绑定的协议类型。具体的参见msdn,不详细叙述了。
    2.IPEndPoint(ip, port);我理解我建立一个IP终端,ip为ip地址,port为监听的端口。
    3.socket.Bind(Ipendpoint);将终端和套接字绑定
    4.socket.Listen(500);socket的监听函数,参数为最多挂起数目。()
    5.Connected:网络的连接情况    
    6.socket.Accept();获取远程请求的socket套接字
    7.temp_socket.Receive(recvBytes, recvBytes.Length, 0);接收函数,recvBytes为接收缓冲区,第二个参数为数据长度,第三个参数为缓冲区起始位置。
    8.temp_socket.Send(Byte[]); //发送数据  
    9. temp_socket.Close();//关闭socket连接
   以上是同步socket的一些基本的函数,两天时间本人也还没来得及细细研究每个函数的具体意义和各种重载,粗略记录其基本的作用。对应于异步的socket收发,由于线程不再没有数据的时候阻塞,因此采用回调函数的形式操作socket的连接,数据的接受和发送。其中涉及线程的阻塞与唤醒,在接下来的代码中大家可以研究下期间的细节。异步的socket通信包含了几组常用的函数如下:
   1.(连接)
   tcpsend.BeginConnect(end, new AsyncCallback(ConnectedCallback), tcpsend); //调用回调函数(1)
   与
    client.EndConnect(ar);(2)
   其中(1)操作将线程挂起,调用回调函数执行余下的操作,(2)在回调函数中执行,这才算真正的连接完毕,然后唤醒线程执行余下的操作。
  2.(发送)
  tcpsend.BeginSend(Bysend, 0, Bysend.Length, 0, new AsyncCallback(SendCallback), tcpsend); //异步发送数据
  与
  int bytesSend = client.EndSend(ar);  //完成发送
3.(接收)
   tcpsend.BeginReceive(receive_buff, 0, receive_buff.Length, 0, new AsyncCallback(ReceiveCallback), tcpsend);

   int bytesread = client.EndReceive(ar);
   以上三组完成了socket的连接,读写数据的异步操作,异步的优点是不会因为socket端口被单一的线程堵塞时造成其他连接的丢失,多个线程能够保持独立不受影响。
  下面 给出源代码:
   Socket同步通信
(Server)

  using System;using System.Collections.Generic;

using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Net;using System.Net.Sockets;using System.Threading;using System.Collections;namespace SocketReceive{    public partial class Form1 : Form    {        public int port = 8000;        public Thread threadread;        public IPEndPoint tcplisener;         public bool listen_flag = false;        public Socket read;        public string server_ip = "192.168.1.110";        public Thread accept;        Thread[] SocketThreadList=new Thread[100];        public Form1()        {            InitializeComponent();        }        private void button1_Click(object sender, EventArgs e)        {            IPAddress ip = IPAddress.Parse(server_ip);            //用指定ip和端口号初始化            tcplisener = new IPEndPoint(ip, port);            //创建一个socket对象            read = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);            try            {                read.Bind(tcplisener); //绑定                ///收到客户端的连接,建立新的socket并接受信息                read.Listen(500); //开始监听                textBox1.Text = " 等待客户端连接";                accept = new Thread(new ThreadStart(Listen));                accept.Start();            }            catch            {                MessageBox.Show("Error");            }            GC.Collect();            GC.WaitForPendingFinalizers();        }        public void Listen()        {            Thread.CurrentThread.IsBackground = true; //后台线程            while (true)            {                Socket temp_socket = read.Accept();                textBox1.Text = "建立连接";                IPEndPoint remoteaddr = (IPEndPoint)temp_socket.RemoteEndPoint;//获取远程的ip地址                textBox1.Text = "接收来自" + remoteaddr + "的连接";                threadread=new Thread(new ParameterizedThreadStart(AcceptThread));                threadread.Start(temp_socket);//将连接传递给子线程                            }        }        /// </summary>        public void AcceptThread(object socket)         {            Socket temp_socket = (Socket)socket;            try            {                while(temp_socket.Connected)                {                if(temp_socket.Connected)                {                byte[] recvBytes = new byte[1024];                int bytes;                string recvstr = "";                bytes = temp_socket.Receive(recvBytes, recvBytes.Length, 0);//从客户端接受信息                recvstr += Encoding.ASCII.GetString(recvBytes, 0, bytes);                richTextBox1.Text = recvstr;                //          MessageBox.Show(recvstr);                temp_socket.Send(Encoding.Default.GetBytes("Got!" + recvstr)); //回发数据                   temp_socket.Close();                Thread.Sleep(100);                 }                else                {                    temp_socket.Close();                    break;                }                }            }            catch            {                MessageBox.Show("侦听失败", "错误");            }        }        }    }

  Client端
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Net;using System.Net.Sockets;namespace SocketTest{    public partial class Form1 : Form    {       public SocketClient send = new SocketClient(); //构造socket客户端实例        public Form1()        {            InitializeComponent();        }        private void button1_Click(object sender, EventArgs e)        {            if (send.connect(textBox2.Text) == true)            {                textBox1.Text = "成功连接远程计算机";            }            else            {                textBox1.Text = "连接失败";            }        }        private void button2_Click(object sender, EventArgs e)        {            try            {                send.send(richTextBox1.Text);                textBox1.Text = "发送成功";                byte[] back = new byte[1024];                int count = send.tcpsend.Receive((back));                richTextBox2.Text = Encoding.ASCII.GetString(back, 0, count);                send.tcpsend.Close();            }            catch            {                textBox1.Text = "发送异常";            }        }        private void Form1_Leave(object sender, EventArgs e)        {            send.tcpsend.Close();        }    }}
  其中SocketClient为   public class SocketClient    {       public  int port=8000;                //监听端口号       public  TcpClient tcpc;       //对服务器端建立TCP连接       public  Socket tcpsend;          //发送创建套接字       public  bool connect_flag=false;       public byte[] receive_buff = new byte[1024];       public ManualResetEvent connectDone = new ManualResetEvent(false); //连接的信号       public ManualResetEvent readDone = new ManualResetEvent(false);    //读信号       public ManualResetEvent sendDone = new ManualResetEvent(false);    //发送结束        public bool connect(string address)        {            try{                tcpsend = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);//初始化套接字                 IPEndPoint remotepoint = new IPEndPoint(IPAddress.Parse(address),port);//根据ip地址和端口号创建远程终结点                  EndPoint end = (EndPoint)remotepoint;              //  tcpsend.Connect(end);              //  connect_flag = true;                  tcpsend.BeginConnect(end, new AsyncCallback(ConnectedCallback), tcpsend); //调用回调函数                  connectDone.WaitOne();                  return true;            }            catch            {                return false;            }        }        private void ConnectedCallback(IAsyncResult ar)       {           Socket client = (Socket)ar.AsyncState;           client.EndConnect(ar);//           connect_flag = true;           connectDone.Set();       }        public void send(string data)        {            int length = data.Length;            Byte[] Bysend = new byte[length];            Bysend = System.Text.Encoding.Default.GetBytes(data); //将字符串指定到指定Byte数组            tcpsend.BeginSend(Bysend, 0, Bysend.Length, 0, new AsyncCallback(SendCallback), tcpsend); //异步发送数据            //int i = tcpsend.Send(Bysend);                         //发送数据             sendDone.WaitOne();        }        private void SendCallback(IAsyncResult ar) //发送的回调函数        {            Socket client = (Socket)ar.AsyncState;            int bytesSend = client.EndSend(ar);  //完成发送            sendDone.Set();         }        public void receive()   //接收数据        {            //byte[] receive=new byte[1024];            tcpsend.BeginReceive(receive_buff, 0, receive_buff.Length,0, new AsyncCallback(ReceiveCallback), tcpsend);        }        private void ReceiveCallback(IAsyncResult ar)        {            Socket client = (Socket)ar.AsyncState; //获取句柄            int bytesread = client.EndReceive(ar);            if (bytesread > 0)            {                tcpsend.BeginReceive(receive_buff, 0, receive_buff.Length, 0, new AsyncCallback(ReceiveCallback), client);            }            else            {                readDone.Set();            }        }
  以上是Socket同步的通信,读者可以无视控件的操作,在控制台程序中实现便可,不用我这么繁琐。
     下面是异步的通信形式:
   Server:using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Net;using System.Net.Sockets;using System.Threading;using System.Collections;namespace SocketReceive{    public partial class Form1 : Form    {        public int port = 8000;        public Thread threadread;        public IPEndPoint tcplisener;         public bool listen_flag = false;        public Socket read;        public string server_ip = "192.168.1.110";        public Thread accept;        public ManualResetEvent AcceptDone = new ManualResetEvent(false); //连接的信号        public Form1()        {            InitializeComponent();        }        private void button1_Click(object sender, EventArgs e)        {            IPAddress ip = IPAddress.Parse(server_ip);            //用指定ip和端口号初始化            tcplisener = new IPEndPoint(ip, port);            //创建一个socket对象            read = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);            read.Bind(tcplisener); //绑定            ///收到客户端的连接,建立新的socket并接受信息            read.Listen(500); //开始监听            textBox1.Text = " 等待客户端连接";            accept = new Thread(new ThreadStart(Listen));            accept.Start();          //  Listen();            GC.Collect();            GC.WaitForPendingFinalizers();                    }        public void Listen()        {            //Thread.CurrentThread.IsBackground = true; //后台线程            try            {                while (true)                {                    AcceptDone.Reset();                    //Socket temp_socket = read.Accept();                    read.BeginAccept(new AsyncCallback(AcceptCallback), read);  //异步调用                    AcceptDone.WaitOne();                }            }            catch(Exception er)            {                MessageBox.Show(er.Message);            }        }        public void AcceptCallback(IAsyncResult ar) //accpet的回调处理函数        {            AcceptDone.Set();            Socket temp_socket = (Socket)ar.AsyncState;            Socket client = temp_socket.EndAccept(ar); //获取远程的客户端            textBox1.Text = "建立连接";            IPEndPoint remotepoint = (IPEndPoint)client.RemoteEndPoint;//获取远程的端口            string remoteaddr = remotepoint.Address.ToString();        //获取远程端口的ip地址            textBox1.Text = "接收来自" + remoteaddr + "的连接";            StateObject state = new StateObject();            state.workSocket = client;            client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);        }        /// </summary>        public  void ReadCallback(IAsyncResult ar)        {            String content = String.Empty;            // Retrieve the state object and the handler socket            // from the asynchronous state object.            StateObject state = (StateObject)ar.AsyncState;            Socket handler = state.workSocket;            // Read data from the client socket.             int bytesRead = handler.EndReceive(ar);            if (bytesRead > 0)            {                string contentstr = ""; //接收到的数据                contentstr += Encoding.ASCII.GetString(state.buffer, 0, bytesRead);                richTextBox1.Text = contentstr;                byte[] byteData=Encoding.ASCII.GetBytes("Success:"+contentstr);//回发信息                handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);                handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);            }        }        private  void Send(Socket handler, String data)        {            // Convert the string data to byte data using ASCII encoding.            byte[] byteData = Encoding.ASCII.GetBytes(data);            // Begin sending the data to the remote device.            handler.BeginSend(byteData, 0, byteData.Length, 0,                new AsyncCallback(SendCallback), handler);        }        private  void SendCallback(IAsyncResult ar)        {            try            {                // Retrieve the socket from the state object.           //     Socket handler = (Socket)ar.AsyncState;                // Complete sending the data to the remote device.          //      int bytesSent = handler.EndSend(ar);               // Console.WriteLine("Sent {0} bytes to client.", bytesSent);          //      richTextBox1.Text = "Send" + bytesSent.ToString() + "bytes to client.";          //      handler.Shutdown(SocketShutdown.Both);           //     handler.Close();            }            catch (Exception e)            {                MessageBox.Show(e.ToString());            }        }        }    public class StateObject    {        // Client  socket.        public Socket workSocket = null;        // Size of receive buffer.        public const int BufferSize = 1024;        // Receive buffer.        public byte[] buffer = new byte[BufferSize];        // Received data string.        public StringBuilder sb = new StringBuilder();    }    }
  Clientusing System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace SocketTest
{
    public partial class Form1 : Form
    {
        public int port = 8000;                //监听端口号
        public TcpClient tcpc;       //对服务器端建立TCP连接
        public Socket tcpsend;          //发送创建套接字
        public bool connect_flag = false;
        public byte[] receive_buff = new byte[1024];
        public ManualResetEvent connectDone = new ManualResetEvent(false); //连接的信号
        public ManualResetEvent readDone = new ManualResetEvent(false);    //读信号
        public ManualResetEvent sendDone = new ManualResetEvent(false);    //发送结束

        public bool connect(string address)
        {
            try
            {
                tcpsend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//初始化套接字
                IPEndPoint remotepoint = new IPEndPoint(IPAddress.Parse(address), port);//根据ip地址和端口号创建远程终结点
                EndPoint end = (EndPoint)remotepoint;
                //  tcpsend.Connect(end);
                //  connect_flag = true;
                tcpsend.BeginConnect(end, new AsyncCallback(ConnectedCallback), tcpsend); //调用回调函数
                connectDone.WaitOne();
                return true;
            }
            catch
            {
                return false;
            }
        }

        private void ConnectedCallback(IAsyncResult ar)
        {
            Socket client = (Socket)ar.AsyncState;
            client.EndConnect(ar);//
            connect_flag = true;
            connectDone.Set();
        }

        public void send(string data)
        {
            int length = data.Length;
            Byte[] Bysend = new byte[length];
            Bysend = System.Text.Encoding.Default.GetBytes(data); //将字符串指定到指定Byte数组
            tcpsend.BeginSend(Bysend, 0, Bysend.Length, 0, new AsyncCallback(SendCallback), tcpsend); //异步发送数据
            //int i = tcpsend.Send(Bysend);                         //发送数据
            sendDone.WaitOne();
        }

        private void SendCallback(IAsyncResult ar) //发送的回调函数
        {
            Socket client = (Socket)ar.AsyncState;
            int bytesSend = client.EndSend(ar);  //完成发送
            sendDone.Set();
        }

        public void receive()   //接收数据
        {
            //byte[] receive=new byte[1024];
            tcpsend.BeginReceive(receive_buff, 0, receive_buff.Length, 0, new AsyncCallback(ReceiveCallback), tcpsend);
            sendDone.WaitOne();
        }

        private void ReceiveCallback(IAsyncResult ar)
        {
            Socket client = (Socket)ar.AsyncState; //获取句柄
            int bytesread = client.EndReceive(ar);
            if (bytesread > 0)
            {
                client.BeginReceive(receive_buff, 0, receive_buff.Length, 0, new AsyncCallback(ReceiveCallback), client);
                string content = Encoding.ASCII.GetString(receive_buff, 0, receive_buff.Length);
                richTextBox2.Text = content;// receive_buff.ToString();
            }
            else
            {
                readDone.Set();
            }
        }

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            connectDone.Reset();
            if (connect(textBox2.Text) == true)
            {
                connectDone.WaitOne();
                textBox1.Text = "成功连接远程计算机";
            }
            else
            {
                textBox1.Text = "连接失败";
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            try
            {
            //    sendDone.Reset();
                send(richTextBox1.Text);
             //   sendDone.WaitOne();
                textBox1.Text = "发送成功";
            //    readDone.Reset();
                receive();
            //    readDone.WaitOne();
               // byte[] back = new byte[1024];
               // int count = send.tcpsend.Receive((back));
              //  richTextBox2.Text = Encoding.ASCII.GetString(back, 0, count);
              //  send.tcpsend.Close();
            }
            catch
            {
                textBox1.Text = "发送异常";
            }
        }

        private void Form1_Leave(object sender, EventArgs e)
        {
            tcpsend.Close();
        }

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值