1. 程式人生 > >C#實現伺服器和客戶端之間通訊

C#實現伺服器和客戶端之間通訊

TCP  套接字程式設計

伺服器端實現步驟:

1、使用Socket類建立套接字。

2、利用Bind方法將建立的套接字繫結到指定的地址結構。

3、利用Listen方法設定套接字為監聽模式,使得伺服器進入被動開啟狀態。

4、接受客戶端的連線請求。

5、接收、應答客戶端的資料請求。

6、終止連線。

客戶端實現步驟:

1、使用Socket類建立套接字。

2、呼叫Connect方法建立一個與TCP伺服器的連線。

3、傳送資料請求,接受伺服器的資料應答。

4、終止連線。

一對一:

客戶端程式碼:

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;
namespace Client
{
    class Problem
    {
        private static byte[] result = new byte[1024 * 1024];
        static Socket ClientSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
        static void Main(string[] args)
        {
            int Port = 8222;
            IPAddress IP = IPAddress.Parse("127.0.0.1");
            try
            {
                Console.WriteLine("連線伺服器成功!!!");
                ClientSocket.Connect(new IPEndPoint(IP,Port));
            }
            catch(Exception ex)
            {
                Console.WriteLine("連線伺服器失敗,按回車鍵退出!");
                return;
            }
            for(int i=0;i<10;i++)
            {
                try
                {
                    Thread.Sleep(2000);
                    int ReceiveLength = ClientSocket.Receive(result);
                    Console.WriteLine("接收伺服器訊息:{0}",Encoding.ASCII.GetString(result,0,ReceiveLength));
                    Console.WriteLine("向伺服器傳送訊息:");
                    string sb = Console.ReadLine();
                    string SendMessage = "向伺服器傳送訊息:" + DateTime.Now + "\n" + sb;
                    ClientSocket.Send(Encoding.ASCII.GetBytes(SendMessage));
                }
                catch(Exception ex)
                {
                    ClientSocket.Shutdown(SocketShutdown.Both);
                    ClientSocket.Close();
                }
            }
            Console.WriteLine("訊息傳送完畢!!!");
            Console.WriteLine();
        }
    }
}
伺服器程式碼:
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;
namespace Server
{
    class Program
    {
        public static void ListenClientConnect()
        {
            while(true)
            {
                Socket ClientSocket = ServerSocket.Accept();//send
                Console.WriteLine("向客戶端傳送訊息:");
                string sb = Console.ReadLine();
                ClientSocket.Send(Encoding.ASCII.GetBytes("Server Say Hello:"+sb));
                Thread thread = new Thread(ReceiveMessage);
                thread.Start(ClientSocket);
            }
        }
        public static void ReceiveMessage(Object ClientSocket)
        {
            Socket MyClientSocket = (Socket)ClientSocket;
            while(true)
            {
                try
                {
                    int ReceiveNum = MyClientSocket.Receive(result);
                    Console.WriteLine("接受客戶端{0}訊息{1}:" ,MyClientSocket.RemoteEndPoint.ToString(),
                       Encoding.ASCII.GetString(result,0,ReceiveNum));
                    Console.WriteLine("向客戶端傳送訊息:");
                    string sb = Console.ReadLine();
                    MyClientSocket.Send(Encoding.ASCII.GetBytes(sb));
                }
                catch(Exception ex)
                {
                    Console.WriteLine("404 Not found!!!");
                    MyClientSocket.Shutdown(SocketShutdown.Both);
                    MyClientSocket.Close();
                }
            }
        }
        private static byte[] result = new byte[1024 * 1024];
        static Socket ServerSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
        static void Main(String[] args)
        {
            try
            {
                int Port = 8222;
                IPAddress IP = IPAddress.Parse("127.0.0.1");
                ServerSocket.Bind(new IPEndPoint(IP, Port));
                ServerSocket.Listen(10);
                Console.WriteLine("啟動監聽{0}成功",ServerSocket.LocalEndPoint.ToString());
                Thread thread = new Thread(ListenClientConnect);
                thread.Start();
                Thread.Sleep(2000);
            }
            catch(Exception ex)
            {
                throw ex;
            }
        }
    }
}

一對多:

服務端程式碼:

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;
using System.Linq;
namespace Server
{
    class Program
    {
        public static void ListenConnection()
        {
            Socket ConnectionSocket = null;
            while(true)
            {
                try
                {
                    ConnectionSocket = ServerSocket.Accept();
                }
                catch(Exception ex)
                {
                    Console.WriteLine("監聽套接字異常{0}",ex.Message);
                    break;
                }
                //獲取客戶端埠號和IP
                IPAddress ClientIP=(ConnectionSocket.RemoteEndPoint as IPEndPoint).Address;
                int ClientPort = (ConnectionSocket.RemoteEndPoint as IPEndPoint).Port;
                string SendMessage = "連線伺服器成功\r\n" + "本地IP:" + ClientIP +
                    ",本地埠:" + ClientPort.ToString();
                //Console.WriteLine(SendMessage);
                ConnectionSocket.Send(Encoding.UTF8.GetBytes(SendMessage));
                string remotePoint = ConnectionSocket.RemoteEndPoint.ToString();
                Console.WriteLine("成功與客戶端{0}建立連線!\t\n", remotePoint);
                ClientInformation.Add(remotePoint, ConnectionSocket);
                Thread thread = new Thread(ReceiveMessage);
                thread.IsBackground = true;
                thread.Start(ConnectionSocket);
            }
        }
        public static void ReceiveMessage(Object SocketClient)
        {
            Socket ReceiveSocket = (Socket)SocketClient;
            while(true)
            {
                byte[] result = new byte[1024 * 1024];
                try
                {
                    IPAddress ClientIP = (ReceiveSocket.RemoteEndPoint as IPEndPoint).Address;
                    int ClientPort = (ReceiveSocket.RemoteEndPoint as IPEndPoint).Port;
                    int ReceiveLength = ReceiveSocket.Receive(result);
                    string ReceiveMessage = Encoding.UTF8.GetString(result, 0, ReceiveLength);
                    Console.WriteLine("接收客戶端:" + ReceiveSocket.RemoteEndPoint.ToString()+
                        "時間:"+DateTime.Now.ToString()+"\r\n"+"訊息:"+ReceiveMessage+"\r\n\n");
                    foreach(string key in new List<string>(ClientInformation.Keys))
                    {
                        string s = ReceiveSocket.RemoteEndPoint.ToString();
                        if(key!=s)
                        {
                            Socket socket = ClientInformation[key];
                            Console.WriteLine("向客戶端{0}傳送訊息:", key);
                            socket.Send(Encoding.UTF8.GetBytes(ReceiveMessage));
                        }
                    }
                    //Console.WriteLine("向客戶端{0}傳送訊息:", ReceiveSocket.RemoteEndPoint.ToString());
                    //string sb = Console.ReadLine();
                    //ReceiveSocket.Send(Encoding.UTF8.GetBytes(sb));
                }
                catch(Exception ex)
                {
                    Console.WriteLine("監聽出現異常!!!");
                    Console.WriteLine("客戶端" + ReceiveSocket.RemoteEndPoint + "已經連線中斷" + "\r\n" +
                        ex.Message + "\r\n" + ex.StackTrace + "\r\n");
                    foreach(string key in new List<string>(ClientInformation.Keys))
                    {
                        string s = ReceiveSocket.RemoteEndPoint.ToString();
                        if (key.Equals(s))
                        {
                            ClientInformation.Remove(key);
                        }
                    }
                    ReceiveSocket.Shutdown(SocketShutdown.Both);
                    ReceiveSocket.Close();
                    break;
                }
            }
        }
        //private static byte[] result = new byte[1024];
        //List<Socket> list = new List<Socket>();
        static Dictionary<string, Socket> ClientInformation = new Dictionary<string, Socket> { };
        static Socket ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        static void Main(String[] args)
        {
            try
            {
                int Port = 8333;
                IPAddress IP = IPAddress.Parse("127.0.0.1");
                ServerSocket.Bind(new IPEndPoint(IP, Port));
                ServerSocket.Listen(10);
                Console.WriteLine("啟動監聽成功!");
                Console.WriteLine("監聽本地{0}成功", ServerSocket.LocalEndPoint.ToString());
                Thread ThreadListen = new Thread(ListenConnection);
                ThreadListen.IsBackground = true;
                ThreadListen.Start();
                Thread.Sleep(2000);
            }
            catch(Exception ex)
            {
                Console.WriteLine("監聽異常!!!");
                ServerSocket.Shutdown(SocketShutdown.Both);
                ServerSocket.Close();
            }
            Console.ReadKey();
            Console.WriteLine("監聽完畢,按任意鍵退出!");
        }
    }
}
客戶端程式碼:
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;
namespace Client
{
    class Problem
    {
        private static byte[] result = new byte[1024 * 1024];
        static Socket ClientSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
        public static void ReceiveMessage()
        {
            while(true)
            {
                try
                {
                    int ReceiveLength = ClientSocket.Receive(result);
                    Console.WriteLine("接收伺服器訊息:{0}", Encoding.UTF8.GetString(result, 0, ReceiveLength));
                }
                catch(Exception ex)
                {
                    Console.WriteLine("出現異常了!!!");
                    Console.WriteLine(ex.Message);
                    ClientSocket.Shutdown(SocketShutdown.Both);
                    ClientSocket.Close();
                    break;
                }
            }
        }
        static void Main(string[] args)
        {
            int Port = 8333;
            IPAddress IP = IPAddress.Parse("127.0.0.1");
            try
            {
                ClientSocket.Connect(new IPEndPoint(IP,Port));
                Thread thread = new Thread(ReceiveMessage);
                thread.Start();
                Thread.Sleep(2000);
            }
            catch(Exception ex)
            {
                Console.WriteLine("連線伺服器失敗,按回車鍵退出!");
                return;
            }
            Console.WriteLine("連線伺服器成功!!!");
            //int ReceiveLength = ClientSocket.Receive(result);
            //Console.WriteLine("接收伺服器訊息:{0}", Encoding.UTF8.GetString(result, 0, ReceiveLength));
            while (true)
            {
                try
                {
                    Thread.Sleep(2000);
                    Console.WriteLine("向伺服器傳送訊息:");
                    string sb = Console.ReadLine();
                    string Client = ClientSocket.RemoteEndPoint.ToString();
                    string SendMessage = "接收客戶端" + Client + "訊息:" + DateTime.Now + "\n" + sb;
                    ClientSocket.Send(Encoding.ASCII.GetBytes(sb));
                }
                catch(Exception ex)
                {
                    ClientSocket.Shutdown(SocketShutdown.Both);
                    ClientSocket.Close();
                    break;
                }
            }
            Console.WriteLine("訊息傳送完畢!!!");
            Console.ReadLine();
        }
    }
}

下面是一對多的使用窗體介面顯示的程式碼以及顯示效果:

客戶端程式碼:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.IO;
namespace ClientForm
{
    public partial class Form1 : Form
    {
        private byte[] result = new byte[1024 * 1024];
        private Socket ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        public Form1()
        {
            InitializeComponent();
            TextBox.CheckForIllegalCrossThreadCalls = false;
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            ;
        }
        private void textBox1_TextChanged(object sender, EventArgs e)//輸入訊息
        {
            //;
            string str = Console.ReadLine();
            textBox1.Text += str;
        }
        private void textBox2_TextChanged(object sender, EventArgs e)//ip
        {
            ;
        }
        private void textBox3_TextChanged(object sender, EventArgs e)//port
        {
            ;
        }
        private void button1_Click(object sender, EventArgs e)//傳送訊息
        {
            try
            {
                //Thread.Sleep(2000);
                richTextBox1.Text += "向伺服器傳送訊息:\r\n";
                richTextBox1.Text += textBox1.Text + "\r\n";
                string sb = textBox1.Text;
                string Client = ClientSocket.RemoteEndPoint.ToString();
                string SendMessage = "接收客戶端" + Client + "訊息:" + DateTime.Now + "\r\n" + sb + "\r\n";
                ClientSocket.Send(Encoding.UTF8.GetBytes(sb));
                textBox1.Clear();
            }
            catch (Exception ex)
            {
                richTextBox1.Text += "伺服器可能已經關閉!\r\n";
                ClientSocket.Shutdown(SocketShutdown.Both);
                ClientSocket.Close();
            }
        }
        private void button2_Click(object sender, EventArgs e)//連線伺服器
        {
            int Port = Convert.ToInt32(textBox3.Text);
            IPAddress IP = IPAddress.Parse((string)textBox2.Text);
            try
            {
                ClientSocket.Connect(new IPEndPoint(IP, Port));
                richTextBox2.Text += "連線伺服器成功!\r\n";
                Thread thread = new Thread(ReceiveMessage);
                thread.IsBackground = true;
                thread.Start();
            }
            catch (Exception ex)
            {
                richTextBox2.Text += "連線伺服器失敗!\r\n";
                return;
            }
        }
        private void label1_Click(object sender, EventArgs e)
        {
            ;
        }
        private void label2_Click(object sender, EventArgs e)
        {
            ;
        }
        private void richTextBox1_TextChanged(object sender, EventArgs e)//顯示傳送的訊息
        {
            ;
        }
        private void richTextBox2_TextChanged(object sender, EventArgs e)//顯示接收的訊息
        {
            ;
        }
        private void ReceiveMessage()
        {
            while (true)
            {
                try
                {
                    int ReceiveLength = ClientSocket.Receive(result);
                    richTextBox2.Text += "接收伺服器訊息:\r\n";
                    string str = Encoding.UTF8.GetString(result, 0, ReceiveLength)+"\r\n";
                    richTextBox2.Text += str;
                }
                catch (Exception ex)
                {
                    richTextBox2.Text += "接收訊息失敗!\r\n";
                    ClientSocket.Shutdown(SocketShutdown.Both);
                    ClientSocket.Close();
                    break;
                }
            }
        }
    }
}

服務端程式碼:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.IO;
using System.Threading;
namespace ServerForm
{
    public partial class Form1 : Form
    {
        private byte[] result = new byte[1024 * 1024];
        private Socket ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        private Dictionary<string, Socket> ClientInformation = new Dictionary<string, Socket> { };
        public Form1()
        {
            InitializeComponent();
            TextBox.CheckForIllegalCrossThreadCalls = false;
            //在多執行緒程式中,新建立的執行緒不能訪問UI執行緒建立的視窗控制元件
            //如果需要訪問視窗控制元件則可以如此設定
        }
        private void label1_Click(object sender, EventArgs e)//ip
        {

        }
        private void label2_Click(object sender, EventArgs e)//Port
        {

        }
        private void label3_Click(object sender, EventArgs e)//線上列表
        {

        }
        private void richTextBox1_TextChanged(object sender, EventArgs e)//顯示客戶端之間/客戶端訊息
        {

        }
        private void richTextBox2_TextChanged(object sender, EventArgs e)//顯示連線成功或者掉線的客戶端
        {

        }
        private void richTextBox3_TextChanged(object sender, EventArgs e)//顯示線上列表
        {

        }
        private void textBox1_TextChanged(object sender, EventArgs e)//IP
        {

        }
        
        private void textBox2_TextChanged(object sender, EventArgs e)//Port
        {

        }
        private void button1_Click(object sender, EventArgs e)//啟動服務
        {
            try
            {
                int Port = Convert.ToInt32(textBox2.Text);
                IPAddress IP = IPAddress.Parse((string)textBox1.Text);
                ServerSocket.Bind(new IPEndPoint(IP, Port));
                ServerSocket.Listen(10);
                richTextBox2.Text += "啟動監聽成功!\r\n";
                richTextBox2.Text += "監聽本地" + ServerSocket.LocalEndPoint.ToString() + "成功\r\n";
                Thread ThreadListen = new Thread(ListenConnection);
                ThreadListen.IsBackground = true;
                ThreadListen.Start();
                Thread.Sleep(2000);
            }
            catch(Exception ex)
            {
                richTextBox2.Text += "監聽異常!!!\r\n";
                ServerSocket.Shutdown(SocketShutdown.Both);
                ServerSocket.Close();
            }
        }
        private void ListenConnection()
        {
            Socket ConnectionSocket = null;
            while (true)
            {
                try
                {
                    ConnectionSocket = ServerSocket.Accept();
                }
                catch (Exception ex)
                {
                    richTextBox2.Text += "監聽套接字異常" + ex.Message;
                    //Console.WriteLine("監聽套接字異常{0}", ex.Message);
                    break;
                }
                //獲取客戶端埠號和IP
                IPAddress ClientIP = (ConnectionSocket.RemoteEndPoint as IPEndPoint).Address;
                int ClientPort = (ConnectionSocket.RemoteEndPoint as IPEndPoint).Port;
                string SendMessage = "本地IP:" + ClientIP +
                    ",本地埠:" + ClientPort.ToString();
                ConnectionSocket.Send(Encoding.UTF8.GetBytes(SendMessage));
                string remotePoint = ConnectionSocket.RemoteEndPoint.ToString();
                richTextBox2.Text += "成功與客戶端" + remotePoint + "建立連線\r\n";
                richTextBox3.Text += DateTime.Now+":"+remotePoint + "\r\n";
                ClientInformation.Add(remotePoint, ConnectionSocket);
                Thread thread = new Thread(ReceiveMessage);
                thread.IsBackground = true;
                thread.Start(ConnectionSocket);
            }
        }
        private void ReceiveMessage(Object SocketClient)
        {
            Socket ReceiveSocket = (Socket)SocketClient;
            while (true)
            {
                byte[] result = new byte[1024 * 1024];
                try
                {
                    IPAddress ClientIP = (ReceiveSocket.RemoteEndPoint as IPEndPoint).Address;
                    int ClientPort = (ReceiveSocket.RemoteEndPoint as IPEndPoint).Port;
                    int ReceiveLength = ReceiveSocket.Receive(result);
                    string str = ReceiveSocket.RemoteEndPoint.ToString();
                    string ReceiveMessage = Encoding.UTF8.GetString(result, 0, ReceiveLength);
                    richTextBox1.Text+= "接收客戶端:" + ReceiveSocket.RemoteEndPoint.ToString() +
                    "時間:" + DateTime.Now.ToString() + "\r\n" + "訊息:" + ReceiveMessage + "\r\n";
                    if (ClientInformation.Count == 1) continue;//只有一個客戶端
                    List<string> test = new List<string>(ClientInformation.Keys);
                    for (int i = 0; i < ClientInformation.Count; i++)
                    {
                        Socket socket = ClientInformation[test[i]];
                        string s = ReceiveSocket.RemoteEndPoint.ToString();
                        if (test[i] != s)
                        {
                            richTextBox1.Text += DateTime.Now + "\r\n" + "客戶端" + str + "向客戶端" + test[i] + "傳送訊息:" + ReceiveMessage;
                            string ReceiveMessage1 = DateTime.Now + "\r\n" + "客戶端" + str + "向您傳送訊息:" + ReceiveMessage;
                            socket.Send(Encoding.UTF8.GetBytes(ReceiveMessage1));
                        }
                    }
                }
                catch (Exception ex)
                {
                    richTextBox2.Text += "監聽出現異常!\r\n";
                    richTextBox2.Text += "客戶端" + ReceiveSocket.RemoteEndPoint + "已經連線中斷" + "\r\n" +
                    ex.Message + "\r\n" + ex.StackTrace + "\r\n";
                    string s = ReceiveSocket.RemoteEndPoint.ToString();
                    ClientInformation.Remove(s);
                    ReceiveSocket.Shutdown(SocketShutdown.Both);
                    ReceiveSocket.Close();
                    break;
                }
            }
        }
    }
}
介面效果:

注:我這裡在線列表顯示的是所有連線過伺服器的客戶端,對於可能出現的亂碼問題,將相應的ASCII改為UTF-8即可

新手我建議可以先看這兩位博主的文章:

https://www.cnblogs.com/vaevvaev/p/6865968.html

https://www.cnblogs.com/yy3b2007com/p/7476458.html

客戶端:


伺服器: