C# TCP/IP 服务端 和 客户端

Serve

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


class TcpIpServerEx
{
    public EndPoint RemoteEndPoint { get; private set; } //当前客户端的网络结点
    public Action Debug_Output_string; //调试信息
    public Action Rev_Msg; //收到消息事件


    private bool isRev = true; //是否接受
    Thread threadwatch = null;//负责监听客户端的线程
    Socket socket = null;//负责监听客户端的套接字
                         // Dictionary 定义一个集合,存储客户端信息
    public Dictionary dic = new Dictionary { };


    List list_Thread = new List();

    private StringBuilder msg = new StringBuilder();
    public string Msg
    {
        get { return msg.ToString(); }
        private set
        {
            msg.AppendLine(value);
         //   Console.WriteLine(value + "\r\n");
            if(Debug_Output_string != null)
                 Debug_Output_string("\r\n" + value + "\r\n");
        }
    }

    public void Close()//当 客户端 没有关闭socket时 ,调用Close 就会导致错误
    {
        //先关闭soket 再关闭线程
        isRev = false;

        var dict = dic;
        var keys = dict.Keys.ToList();
        for (int i = dict.Count-1; i >=0 ; i--)
        {
            var Value = dict[keys[i]];
            Value?.Close();
        }
        socket?.Close();

        for (int i = 0; i < list_Thread.Count; i++)
        {
            list_Thread[i]?.Abort();
        }
        threadwatch?.Abort();
        dict.Clear();
        list_Thread.Clear();



    }


    private TcpIpServerEx() { }
    public TcpIpServerEx(int port)
    {
        //定义一个套接字用于监听客户端发来的消息,包含三个参数(IP4寻址协议,流式连接,Tcp协议)
        socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        //将IP地址和端口号绑定到网络节点point上
        IPEndPoint point = new IPEndPoint(IPAddress.Any, port);//设置服务器端口,IP是本程序所在PC的内网IP

        //监听绑定的网络节点
        socket.Bind(point);

        //将套接字的监听队列长度限制为20
        socket.Listen(20);

        //创建一个监听线程
        threadwatch = new Thread(watchconnecting);

        //将窗体线程设置为与后台同步,随着主线程结束而结束
        threadwatch.IsBackground = true;

        //启动线程   
        threadwatch.Start();

        //启动线程后显示相应提示
        Msg = ("开始监听客户端传来的信息!" + "\r\n");
    }

    public TcpIpServerEx(IPEndPoint point)
    {
        //定义一个套接字用于监听客户端发来的消息,包含三个参数(IP4寻址协议,流式连接,Tcp协议)
        socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        //监听绑定的网络节点
        socket.Bind(point);

        //将套接字的监听队列长度限制为20
        socket.Listen(20);

        //创建一个监听线程
        threadwatch = new Thread(watchconnecting);

        //将窗体线程设置为与后台同步,随着主线程结束而结束
        threadwatch.IsBackground = true;

        //启动线程   
        threadwatch.Start();

        //启动线程后显示相应提示
        Msg = ("开始监听客户端传来的信息!" + "\r\n");
    }

    public TcpIpServerEx(IPEndPoint point,Action debugOutputString)
    {
        Debug_Output_string = debugOutputString;
        //定义一个套接字用于监听客户端发来的消息,包含三个参数(IP4寻址协议,流式连接,Tcp协议)
        socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        //监听绑定的网络节点
        socket.Bind(point);

        //将套接字的监听队列长度限制为20
        socket.Listen(20);

        //创建一个监听线程
        threadwatch = new Thread(watchconnecting);

        //将窗体线程设置为与后台同步,随着主线程结束而结束
        threadwatch.IsBackground = true;

        //启动线程   
        threadwatch.Start();

        //启动线程后显示相应提示
        Msg = ("开始监听客户端传来的信息!" + "\r\n");

    }

    //监听客户端发来的请求
    private void watchconnecting()
    {
        Socket connection = null;
        while (isRev)  //持续不断监听客户端发来的请求   
        {
            try
            {
                connection = socket.Accept();
                //让客户显示"连接成功的"的信息
                string sendmsg = "连接服务端成功!你的IP是" + connection.RemoteEndPoint;
                byte[] arrSendMsg = Encoding.UTF8.GetBytes(sendmsg);
                connection.Send(arrSendMsg);

                RemoteEndPoint = connection.RemoteEndPoint; //客户端网络结点号
                Msg = ("成功与" + RemoteEndPoint + "客户端建立连接!\t\n");     //显示与客户端连接情况
                dic.Add(RemoteEndPoint, connection);    //添加客户端信息

                //创建一个通信线程    
                var pts = new ParameterizedThreadStart(recv);
                var thread = new Thread(pts);
                list_Thread.Add(thread);
                //   thread.IsBackground = true;//设置为后台线程,随着主线程退出而退出           
                thread.Start(connection);//启动线程  
            }
            catch (Exception ex)
            {
                Msg = (ex.Message); //提示套接字监听异常   
                break;
            }


        }
    }

    ///   
    /// 接收客户端发来的信息    
    ///   
    ///客户端套接字对象  
    private void recv(object socketclientpara)
    {

        Socket socketServer = socketclientpara as Socket;
        while (isRev)
        {
            //创建一个内存缓冲区 其大小为1024*1024字节  即1M   
            byte[] arrServerRecMsg = new byte[1024 * 1024];
            //将接收到的信息存入到内存缓冲区,并返回其字节数组的长度  
            try
            {
                int length = socketServer.Receive(arrServerRecMsg);

                if (length != 0)
                {
                    //将机器接受到的字节数组转换为人可以读懂的字符串   
                    string strSRecMsg = Encoding.UTF8.GetString(arrServerRecMsg, 0, length);
                    if (Rev_Msg != null) Rev_Msg(strSRecMsg);

                    //将发送的字符串信息附加到文本框txtMsg上   
                    Msg = ("客户端:" + GetCurrentTime() + socketServer.RemoteEndPoint + "的消息:" + strSRecMsg + "\r\n");
                }
        
            }
            catch (Exception ex)
            {
                Msg = ("客户端:" + GetCurrentTime() + socketServer.RemoteEndPoint + "已经中断连接" + "\r\n"); //提示套接字监听异常 
                dic.Remove(socketServer.RemoteEndPoint);
                socketServer.Close();//关闭之前accept出来的和客户端进行通信的套接字
                break;
            }
        }


    }


    //获取当前系统时间
    private string GetCurrentTime()
    {
        string timeStr = System.DateTime.Now.ToString("yyyy年MM月dd日hh时mm分ss秒fff毫秒。");
        return timeStr;
    }

    /// 
    /// 发送信息到客户端
    /// 
    /// 
    /// 要发送的信息
    public void Sent(EndPoint endPoint, string sendMsg)
    {
        byte[] bytes = System.Text.Encoding.UTF8.GetBytes(sendMsg);   //将要发送的信息转化为字节数组,因为Socket发送数据时是以字节的形式发送的
        dic[endPoint].Send(bytes);   //发送数据
        Msg = (GetCurrentTime() + endPoint + "的消息:" + sendMsg + "\r\n");
    }

    public void CloseEndPoint(EndPoint iPoint)
    {
        if (dic.ContainsKey(iPoint))
        {
            dic[iPoint].Close();
            dic.Remove(iPoint);
        }
    }


}

Client 

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

public class TcpIpClintEx
{
    //创建 1个客户端套接字 和1个负责监听服务端请求的线程
    Thread threadclient = null;
    public Socket socket = null;
    public Action Debug_Output_string; //调试信息
    public Action Rev_Msg; //收到消息事件
    private bool isRev = true; //是否接受
    List mlist = new List();
    private StringBuilder msg = new StringBuilder();
    public string Msg
    {
        get { return msg.ToString(); }
        private set
        {
            msg.AppendLine(value);
         //   Console.WriteLine(value + "\r\n");
            if (Debug_Output_string != null)
                Debug_Output_string("\r\n" + value + "\r\n");
        }
    }

    private TcpIpClintEx() { }
    public TcpIpClintEx(string ip, int port)
    {
        //定义一个套接字监听
        socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        //将获取的IP地址和端口号绑定在网络节点上
        IPEndPoint point = new IPEndPoint(IPAddress.Parse(ip), port);
        Msg = "正在连接服务器 " + ip + ":" + port;

        try
        {
            //客户端套接字连接到网络节点上,用的是Connect
            socket.Connect(point);
        }
        catch (Exception)
        {
            Msg = ("连接失败\r\n");
            return;
        }

        threadclient = new Thread(Rev);
        threadclient.IsBackground = true;
        threadclient.Start();
    }

    public TcpIpClintEx(IPEndPoint point)
    {
        //定义一个套接字监听
        socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        Msg = "正在连接服务器 " + point.Address + ":" + point.Port;

        try
        {
            //客户端套接字连接到网络节点上,用的是Connect
            socket.Connect(point);
        }
        catch (Exception)
        {
            Msg = ("连接失败\r\n");
            return;
        }

        threadclient = new Thread(Rev);
        threadclient.IsBackground = true;
        threadclient.Start();
    }
    public TcpIpClintEx(IPEndPoint point, Action debugOutputString)
    {
        Debug_Output_string = debugOutputString;
        //定义一个套接字监听
        socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        Msg = "正在连接服务器 " + point.Address + ":" + point.Port;

        try
        {
            //客户端套接字连接到网络节点上,用的是Connect
            socket.Connect(point);
        }
        catch (Exception)
        {
            Msg = ("连接失败\r\n");
            return;
        }

        threadclient = new Thread(Rev);
        threadclient.IsBackground = true;
        threadclient.Start();
    }

    // 接收服务端发来信息的方法  
    private void Rev()//
    {
        while (isRev && socket.Connected)//持续监听服务端发来的消息
        {
            try
            {
                //定义一个1M的内存缓冲区,用于临时性存储接收到的消息
                byte[] arrRecvmsg = new byte[1024 * 1024];

                //将客户端套接字接收到的数据存入内存缓冲区,并获取长度
                int length = socket.Receive(arrRecvmsg);

                if (length != 0)
                {
                    //将套接字获取到的字符数组转换为人可以看懂的字符串
                    string strRevMsg = Encoding.UTF8.GetString(arrRecvmsg, 0, length);

                    if (Rev_Msg != null) Rev_Msg(strRevMsg);

                    Msg = ("服务器:" + GetCurrentTime() + "IP:" + socket.RemoteEndPoint + ",的消息:" + strRevMsg + "\r\n\n");
                }

            }
            catch (Exception ex)
            {
                Msg = ("远程服务器已经中断连接" + "\r\n");
                break;
            }
        }
    }

    public void Close()
    {
        isRev = false;
        socket?.Close();
        threadclient?.Abort();
    }

    //获取当前系统时间
    private string GetCurrentTime()
    {
        string timeStr = System.DateTime.Now.ToString("yyyy年MM月dd日hh时mm分ss秒fff毫秒。");
        return timeStr;
    }

    //发送字符信息到服务端的方法
    public void Send(string sendMsg)
    {


        //将输入的内容字符串转换为机器可以识别的字节数组   
        byte[] bytes = System.Text.Encoding.UTF8.GetBytes(sendMsg);

        //调用客户端套接字发送字节数组   
       if(socket.Connected && isRev)
            socket.Send(bytes);
    }
}

 Use

using System;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace Udp
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private bool isConnectServe = false;
        private void button5_Click(object sender, EventArgs e)
        {
            if (isConnectServe)
            {
                if (client != null)
                {
                    client.Close();
                }
                isConnectServe = false;
            }
            else
            {
                IPAddress ip = IPAddress.Parse(textBox10.Text);
                int port = int.Parse(textBox9.Text);
                IPEndPoint ipEndPoint = new IPEndPoint(ip, port);

                //检查端口是否被占用了
                if (LocalPortInUse(ipEndPoint.Port, true))
                {
                    textBox7.AppendText("Local Port:[" + ipEndPoint.Port +
                                        "] already be use ,No Method Open and Listen \r\n");
                    return;
                }
                client = new TcpIpClintEx(ipEndPoint, x => { textBox7.AppendText(x); });
                isConnectServe = true;

            }
            button5.Text = client.socket.Connected ? "Stop Connect" : "Connect";
        }

        private void button3_Click(object sender, EventArgs e)
        {
            client?.Send(textBox5.Text);
        }

        private TcpIpServerEx serve;
        private bool serveIsListen = false;
        private void button6_Click(object sender, EventArgs e)
        {
            if (serveIsListen == false)
            {
                int port = int.Parse(textBox11.Text);
                IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, port);//设置服务器端口,IP是本程序所在PC的内网IP

                //检查端口是否被占用了
                if (LocalPortInUse(ipEndPoint.Port, true))
                {
                    textBox12.AppendText("Local Port:[" + ipEndPoint.Port +
                                         "] already be use ,No Method Open and Listen \r\n");
                    return;
                }
                serve = new TcpIpServerEx(ipEndPoint, x =>
                {
                    textBox12.AppendText(x);

                });
                serve.Rev_Msg += x =>
                {
                    serve.Sent(serve.dic.ElementAt(0).Key, "i Revice Msg " + x);
                };
            }
            else
            {
               serve?.Close();
            }

            serveIsListen = !serveIsListen;
            if (serveIsListen)
            {
                button6.Text = "Stop Port And Listen";
            }
            else
            {
                button6.Text = "Open Port And Listen";
            }

        }

    }
}

 

 

 

 

 

//=====================old====================

服务端

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

namespace TcpIpServer
{
    class TcpIpServerEx
    {
        public EndPoint RemoteEndPoint { get; private set; } //当前客户端的网络结点

        Thread threadwatch = null;//负责监听客户端的线程
        Socket socket = null;//负责监听客户端的套接字
        // Dictionary 定义一个集合,存储客户端信息
        public  Dictionary dic = new Dictionary { };

        private StringBuilder msg = new StringBuilder();
        public string Msg
        {
            get { return msg.ToString(); }
            private set
            {
                msg.AppendLine(value);
                Console.WriteLine(value + "\r\n");
            }

        }

        private TcpIpServerEx() { }
        public TcpIpServerEx( int port=11000)
        {
            //定义一个套接字用于监听客户端发来的消息,包含三个参数(IP4寻址协议,流式连接,Tcp协议)
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            //将IP地址和端口号绑定到网络节点point上
            IPEndPoint point = new IPEndPoint(IPAddress.Any, port);//设置服务器端口,IP是本程序所在PC的内网IP

            //监听绑定的网络节点
            socket.Bind(point);

            //将套接字的监听队列长度限制为20
            socket.Listen(20);

            //创建一个监听线程
            threadwatch = new Thread(watchconnecting);

            //将窗体线程设置为与后台同步,随着主线程结束而结束
            threadwatch.IsBackground = true;

            //启动线程   
            threadwatch.Start();

            //启动线程后显示相应提示
            Msg = ("开始监听客户端传来的信息!" + "\r\n");
        }

        //监听客户端发来的请求
        private void watchconnecting()
        {
            Socket connection = null;
            while (true)  //持续不断监听客户端发来的请求   
            {
                try
                {
                    connection = socket.Accept();
                }
                catch (Exception ex)
                {
                    Msg =(ex.Message); //提示套接字监听异常   
                    break;
                }

                //让客户显示"连接成功的"的信息
                string sendmsg = "连接服务端成功!你的IP是" + connection.RemoteEndPoint;
                byte[] arrSendMsg = Encoding.UTF8.GetBytes(sendmsg);
                connection.Send(arrSendMsg);


                RemoteEndPoint = connection.RemoteEndPoint; //客户端网络结点号
                Msg = ("成功与" + RemoteEndPoint + "客户端建立连接!\t\n");     //显示与客户端连接情况
                dic.Add(RemoteEndPoint, connection);    //添加客户端信息


                //创建一个通信线程    
                ParameterizedThreadStart pts = new ParameterizedThreadStart(recv);
                Thread thread = new Thread(pts);
                thread.IsBackground = true;//设置为后台线程,随着主线程退出而退出           
                thread.Start(connection);//启动线程  
            }
        }

        ///   
        /// 接收客户端发来的信息    
        ///   
        ///客户端套接字对象  
        private void recv(object socketclientpara)
        {

            Socket socketServer = socketclientpara as Socket;
            while (true)
            {
                //创建一个内存缓冲区 其大小为1024*1024字节  即1M   
                byte[] arrServerRecMsg = new byte[1024 * 1024];
                //将接收到的信息存入到内存缓冲区,并返回其字节数组的长度  
                try
                {
                    int length = socketServer.Receive(arrServerRecMsg);

                    //将机器接受到的字节数组转换为人可以读懂的字符串   
                    string strSRecMsg = Encoding.UTF8.GetString(arrServerRecMsg, 0, length);

                    //将发送的字符串信息附加到文本框txtMsg上   
                    Msg = ("客户端:" + GetCurrentTime() + socketServer.RemoteEndPoint +"的消息:"+ strSRecMsg + "\r\n");
                }
                catch (Exception ex)
                {
                    Msg = ("客户端:" + GetCurrentTime() + socketServer.RemoteEndPoint + "已经中断连接" + "\r\n"); //提示套接字监听异常 
                                                                                                //listBoxOnlineList.Items.Remove(socketServer.RemoteEndPoint.ToString());//从listbox中移除断开连接的客户端
                    socketServer.Close();//关闭之前accept出来的和客户端进行通信的套接字
                    break;
                }
            }


        }


        //获取当前系统时间
        private string GetCurrentTime()
        {
            string timeStr = System.DateTime.Now.ToString("yyyy年MM月dd日hh时mm分ss秒fff毫秒。");
            return timeStr;
        }

        /// 
        /// 发送信息到客户端
        /// 
        /// 
        /// 要发送的信息
        public void SentMsg(EndPoint endPoint,string sendMsg)
        {

            byte[] bytes = System.Text.Encoding.UTF8.GetBytes(sendMsg);   //将要发送的信息转化为字节数组,因为Socket发送数据时是以字节的形式发送的
            dic[endPoint].Send(bytes);   //发送数据
            Msg = (GetCurrentTime() + endPoint +"的消息:"+ sendMsg + "\r\n");
        }
    }
}

using System;
namespace TcpIpServer
{
    class Program
    {
        static void Main(string[] args)
        {
            TcpIpServerEx s =new TcpIpServerEx();
            while (true)
            {
                string strSend = Console.ReadLine();
                if (strSend == "exit") break;
                Console.WriteLine("s.dic.Count:"+ s.dic.Count);
                if (s.dic.Count >0)
                {
                    s.SentMsg(s.RemoteEndPoint,strSend);
                }
            }
        }
    }
}

客户端

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

namespace TcpIpClint
{
    public class TcpIpClintEx
    {
        //创建 1个客户端套接字 和1个负责监听服务端请求的线程
        Thread threadclient = null;
        Socket socket = null;
        List mlist = new List();
        private StringBuilder msg = new StringBuilder();
        public string Msg
        {
            get { return msg.ToString(); }
            private set
            {
                msg.AppendLine(value);
                Console.WriteLine(value + "\r\n");
            }
        }

        public TcpIpClintEx(string ip, int port = 11000)
        {
            //定义一个套接字监听
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //将获取的IP地址和端口号绑定在网络节点上
            IPEndPoint point = new IPEndPoint(IPAddress.Parse(ip), port);
            Msg = "正在连接服务器 " + ip + ":" + port;

            try
            {
                //客户端套接字连接到网络节点上,用的是Connect
                socket.Connect(point);
            }
            catch (Exception)
            {
                Msg = ("连接失败\r\n");
                return;
            }

            threadclient = new Thread(recv);
            threadclient.IsBackground = true;
            threadclient.Start();
        }

        // 接收服务端发来信息的方法  
        private void recv()//
        {
            while (true)//持续监听服务端发来的消息
            {
                try
                {
                    //定义一个1M的内存缓冲区,用于临时性存储接收到的消息
                    byte[] arrRecvmsg = new byte[1024 * 1024];

                    //将客户端套接字接收到的数据存入内存缓冲区,并获取长度
                    int length = socket.Receive(arrRecvmsg);

                    //将套接字获取到的字符数组转换为人可以看懂的字符串
                    string strRevMsg = Encoding.UTF8.GetString(arrRecvmsg, 0, length);

                    Msg = ("服务器:" + GetCurrentTime() + "IP:" + socket.RemoteEndPoint + ",的消息:" + strRevMsg + "\r\n\n");
                }
                catch (Exception ex)
                {
                    Msg = ("远程服务器已经中断连接" + "\r\n");
                    break;
                }
            }
        }

        //获取当前系统时间
        private string GetCurrentTime()
        {
            string timeStr = System.DateTime.Now.ToString("yyyy年MM月dd日hh时mm分ss秒fff毫秒。");
            return timeStr;
        }

        //发送字符信息到服务端的方法
        public void ClientSendMsg(string sendMsg)
        {
            //将输入的内容字符串转换为机器可以识别的字节数组   
            byte[] arrClientSendMsg = Encoding.UTF8.GetBytes(sendMsg);
            //调用客户端套接字发送字节数组   
            socket.Send(arrClientSendMsg);
        }
    }
}
using System;
using System.Collections.Generic;
using System.Text;

namespace TcpIpClint
{
    class Program
    {
        static void Main(string[] args)
        {
            TcpIpClintEx tcpIpClintEx =new TcpIpClintEx("122.112.226.109");
           
            while (true)
            {
                string strSend = Console.ReadLine();
                if (strSend == "exit") break;
                tcpIpClintEx.ClientSendMsg(strSend);
            }
        }
    }
}

 

你可能感兴趣的:(C#)