dotnet socket

服务端操作

//1、创建IPE
int port = 6000;
string host = "127.0.0.1";
IPAddress ip = IPAddress.Parse(host);
IPEndPoint ipe = new IPEndPoint(ip, port);

//2、创建socket
Socket sSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//3、绑定端口与ip
//如果要指定本地 IP 地址和端口号,请在调用 Listen 方法之前调用 Bind 方法
sSocket.Bind(ipe);
//4、监听,如果希望基础服务提供商为你分配一个可用端口,请使用端口号零
//如果使用面向连接的协议(例如 TCP),则服务器可以使用 Listen 方法侦听连接
sSocket.Listen(0);

Console.WriteLine("监听已经打开,请等待");

//5、获取通信socket
//receive message, Accept 方法处理任何传入连接请求,并返回可用于与远程主机通信的 Socket
Socket serverSocket = sSocket.Accept();

Console.WriteLine("连接已经建立");
string recStr = "";
byte[] recByte = new byte[4096];
//6、接收数据。若要传递数据,请调用 Send 或 Receive 方法
int bytes = serverSocket.Receive(recByte, recByte.Length, 0);
recStr += Encoding.ASCII.GetString(recByte, 0, bytes);

//send message
Console.WriteLine("服务器端获得信息:{0}", recStr);
string sendStr = "send to client :hello";
byte[] sendByte = Encoding.ASCII.GetBytes(sendStr);
//7、发送数据
serverSocket.Send(sendByte, sendByte.Length, 0);
serverSocket.Close();
sSocket.Close();

client

//1、创建ipe
int port = 6000;
string host = "127.0.0.1";//服务器端ip地址
IPAddress ip = IPAddress.Parse(host);
IPEndPoint ipe = new IPEndPoint(ip, port);

//2、创建socket
Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//3、connect
clientSocket.Connect(ipe);

//4、send message
string sendStr = "send to server : hello,ni hao";
byte[] sendBytes = Encoding.ASCII.GetBytes(sendStr);
clientSocket.Send(sendBytes);

//5、receive message
string recStr = "";
byte[] recBytes = new byte[4096];
int bytes = clientSocket.Receive(recBytes, recBytes.Length, 0);
recStr += Encoding.ASCII.GetString(recBytes, 0, bytes);
Console.WriteLine(recStr);

clientSocket.Close();

下面的代码实现异步:

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

// 客户端请求状态信息保存在这里
public class StateObject
{
    // Client socket. 
    // 客户端的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();
}

public class AsynchronousSocketListener
{

    public static List<Socket> ClientSockets = new List<Socket>();

    // 线程信号  
    public static ManualResetEvent allDone = new ManualResetEvent(false);
    
    /// <summary>
    /// 构造函数
    /// </summary>
    public AsynchronousSocketListener()
    {
    }

    /// <summary>
    /// 开始监听
    /// </summary>
    public static void StartListening()
    {
        // Establish the local endpoint for the socket.  
        // The DNS name of the computer  
        // running the listener is "host.contoso.com".  
        IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
        IPAddress ipAddress = ipHostInfo.AddressList[3];
        IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);

        // Create a TCP/IP socket.  
        Socket listener = new Socket(ipAddress.AddressFamily,
            SocketType.Stream, ProtocolType.Tcp);

        // Bind the socket to the local endpoint and listen for incoming connections.  
        try
        {
            listener.Bind(localEndPoint);
            listener.Listen(100);
            Task.Run(()=> {
                while (true)
                {
                    // Set the event to nonsignaled state.  
                    allDone.Reset();

                    // Start an asynchronous socket to listen for connections. 
                    // AsyncCallback 让回调函数在单独的线程中执行
                    Console.WriteLine("Waiting for a connection...");
                    // 处理传入的请求,这个只有在客户端发起握手的时候才调用
                    listener.BeginAccept(
                        new AsyncCallback(AcceptCallback),
                        listener);

                    // Wait until a connection is made before continuing.                  
                    allDone.WaitOne();
                }
            });

            while (true)
            {

                for (int i = 0; i < ClientSockets.Count; i++)
                {
                    try
                    {
                        Send(ClientSockets[i], "hello i am server
");
                    }
                    catch (Exception)
                    {
                        ClientSockets.RemoveAt(i);
                    }
                }
                Thread.Sleep(100);
            }


        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }

        Console.WriteLine("
Press ENTER to continue...");
        Console.Read();

    }

    /// <summary>
    /// 监听回调
    /// </summary>
    /// <param name="ar"></param>
    public static void AcceptCallback(IAsyncResult ar)
    {
        // 标记主线程继续执行  
        allDone.Set();

        // 获取socket来处理client请求  
        Socket listener = (Socket)ar.AsyncState;
        Socket handler = listener.EndAccept(ar);     

        // 创建数据对象(储存接收数据)
        StateObject state = new StateObject();
        state.workSocket = handler;
        //存储请求来的socket,方便从server发送到client
        ClientSockets.Add(handler);
        Console.WriteLine(ClientSockets.Count);
        // 处理传递进来的数据
        handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
            new AsyncCallback(ReadCallback), state);
    }

    /// <summary>
    /// 读取客户端请求数据回调
    /// </summary>
    /// <param name="ar"></param>
    public static void ReadCallback(IAsyncResult ar)
    {
        String content = String.Empty;

        // Retrieve the state object and the handler socket  
        // from the asynchronous state object.  
        // 在read回调函数中调用 IAsyncResult(ar) 的 AsyncState 方法,以获取传递给 BeginReceive 方法的状态对象
        // 此时就已经获取到客户端请求的数据,存储在state.buffer中,如果此时还有数据进来也不会填充state的buffer,而是等待下一次回调被调用
        StateObject state = (StateObject)ar.AsyncState;
        // 从此状态对象中提取接收 Socket
        Socket handler = state.workSocket;


        // Read data from the client socket.
        // 获取 Client Socket后,可以调用 EndReceive 方法成功完成(关闭) BeginReceive 方法中启动的异步读取操作,并返回所读取的字节数      
        int bytesRead = handler.EndReceive(ar);

        if (bytesRead > 0)
        {
            // There  might be more data, so store the data received so far.
            // 可能会有很多数据要接收,暂存当前已经接收到的数据,StateObject.buffer在ar.AsyncState的时候就已经被填充(实测)
            state.sb.Clear();
            state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));

            // Check for end-of-file tag. If it is not there, read
            // more data. 
            // 检查end-of-file,如果没哟检测到就再继续读。
            content = state.sb.ToString();
            Console.WriteLine(content);
            /*
            if (content.IndexOf("<EOF>") > -1)
            {
                // All the data has been read from the
                // client. Display it on the console.  
                Console.WriteLine("Read {0} bytes from socket. 
 Data : {1}",
                    content.Length, content);
                // Echo the data back to the client.  
                Send(handler, content);
            }
            else
            {
                // Not all data received. Get more.  
                // 没有读取到所有数据,继续读取,这里是个递归
                handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                new AsyncCallback(ReadCallback), state);
            }*/
            handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                new AsyncCallback(ReadCallback), state);
        }
    }

    private static void Send(Socket handler, String data)
    {
        // Convert the string data to byte data using ASCII encoding.  
        // 转换string到字节数组。使用ASCII编码
        byte[] byteData = Encoding.ASCII.GetBytes(data);

        // Begin sending the data to the remote device. 
        // 开始发送,异步发送
        // 这里的handler是客户端client请求来的
        handler.BeginSend(byteData, 0, byteData.Length, 0,
            new AsyncCallback(SendCallback), handler);
    }

    /// <summary>
    /// 发送回调,发送什么如何发送在这里实现
    /// </summary>
    /// <param name="ar"></param>
    private static void SendCallback(IAsyncResult ar)
    {
        try
        {
            // Retrieve the socket from the state object
            // 获取socket ,ar.AsyncState返回的是个object类型,可以转为state也可以转为socket
            Socket handler = (Socket)ar.AsyncState;

            // Complete sending the data to the remote device. 
            // 在回调方法中,调用 IAsyncResult 参数的 AsyncState 方法以获取发送 Socket。 
            // 获取 Socket后,可以调用 EndSend 方法成功完成发送操作,并返回发送的字节数。
            int bytesSent = handler.EndSend(ar);
            //Console.WriteLine("Sent {0} bytes to client.", bytesSent);

            //handler.Shutdown(SocketShutdown.Both);
            //handler.Close();
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }

    public static int Main(String[] args)
    {
        StartListening();
        return 0;
    }
}
原文地址:https://www.cnblogs.com/feipeng8848/p/13218052.html