C# 使用Socket 实现TCP通信的客户端与服务器程序

TCP详细解释就不多说了,直接上代码,关于代码的解释直接在代码的注释中,大家可以去运行看下结果。
下面摘选代码的一部分进行解析,文章最后会附带整体代码。

Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
监控 ip4 地址,套接字类型为 TCP ,协议类型为 TCP
IPAddress.Parse("127.0.0.0")
把ip地址字符串转换为IPAddress类型的实例

sock.Bind(ip); 
目的是绑定本地机器的某个端口,你可以认为此语句将你的电脑的IP地址和端口和本程序内容绑定起来,在通信时就用这个了
 sock.Listen(1); // 侦听中
 监控所有发送到此主机的、特点端口的连接请求。服务端使用,客户端不需要。
Socket client = sock.Accept();
Accept() 以同步方式监听套接字,在连接请求队列中提取第一个挂起的连接请求,然后创建并返回一个新的 Socket 对象。
在没有连接到客户端的时候,程序不会继续进行,直到连接到客户端,即所谓的阻塞进程。
 _sock.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.0"), 8080)); 
 与远程主机建立连接。

更多信息可以看代码注释部分。

完整代码如下:

服务器端:

using System;
using System.Text;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.IO;

namespace ch_Server
{
    
    
    class Server2
    {
    
    
        public static string SendPath = @"G:\Project_C#\ch_Server\chessboard.docx"; // 要发送的文件绝对路径
        static void Main(string[] args)
        {
    
    
            IPEndPoint ip = new IPEndPoint(IPAddress.Parse("127.0.0.0"), 8080); // 服务器端IP,这个可以查看自己电脑的IP地址,端口可以自己设置。
            Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            sock.Bind(ip); 
            sock.Listen(1); // 侦听中
            Socket client = sock.Accept();//暂停当前线程(在这里是主线程),直到有一个客户端连接才会执行下面的语句,并使用返回的Socket跟客户端做通信

            string clientName = client.RemoteEndPoint.ToString();// 输出客户端的IP地址和端口号。
            Console.WriteLine("新客户端连接:" + clientName); 
            SendFile(client); // 发送文件


            while (true) // 传送文件之后的后续工作,这里没啥用,你可以用于别的事情去处理
            {
    
    
                Console.WriteLine("---");
                Thread.Sleep(1000);
            }     
        }
        public static void SendFile(Socket _sock)
        {
    
       
            try
            {
    
                 
                using (FileStream fsReader = new FileStream(SendPath, FileMode.Open, FileAccess.Read, FileShare.None))
                {
    
    
                    long sended = 0L;                   // 初始值为0,L代表长整型。
                    long fileLength = fsReader.Length;  // 要发送文件的长度,字节数
                    string fileName = Path.GetFileName(SendPath);                               //获取一个文件绝对目录的纯文件名字
                    string sendStr = "nameAndLength," + fileName + "," + fileLength.ToString(); // 将文件名字和文件长度发送给接收端

                    _sock.Send(Encoding.Default.GetBytes(sendStr)); // 发送信息

                    const int BUFFERSIZE = 1024;
                    byte[] buffer = new byte[32];

                    int recvCount = _sock.Receive(buffer);// 接收信息到缓冲区
                    string mes = Encoding.Default.GetString(buffer, 0, recvCount);

                    if (mes == "ok")
                    {
    
    
                        Console.WriteLine("发送文件:" + fileName + " 请等待……");
                        byte[] fileBuffer = new byte[BUFFERSIZE];

                        int readCount;
                        int sending;
                        int readCountLeft;

                        while ((readCount = fsReader.Read(fileBuffer, 0, BUFFERSIZE)) != 0)
                        {
    
    
                            sending = 0;
                            readCountLeft = readCount;
                            while ((sending += _sock.Send(fileBuffer, sending, readCountLeft, SocketFlags.None)) < readCount) // 判断发送完
                            {
    
    
                                readCountLeft = readCount - sending;
                            }
                            sended += sending;
                            Console.WriteLine("发送数据:{0}/{1}", sended.ToString(), fileLength.ToString());
                        }

                        Console.WriteLine("发送完毕……\n");
                    }
                }
            }
            catch (Exception ex)
            {
    
    
                Console.WriteLine(ex.Message);
            }
        }

    }
}

客户端:

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace ch_Client
{
    
    
    class Client2
    {
    
    

       
        public static string recivePath= @"G:\Project_C#\ch_Server\";
        static void Main(string[] args)
        {
            
            Socket _sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            _sock.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.0"), 8080)); // 连接服务器,这个要看服务器端的地址是则那样设置的,要保持一致,即要连接到服务器端的Ip地址和端口号。
            Console.WriteLine("连接成功…");

            Thread clientThread = new Thread(new ParameterizedThreadStart(ReceiveFile)); // 开启子线程
            clientThread.IsBackground = true;
            clientThread.Start(_sock); //启动子线程,在这里传参
            clientThread.Join();// 等待子线程结束



            while (true) // 传送文件之后的后续工作,这里没啥用,你可以用于别的事情去处理
            {
    
    
                Console.WriteLine("---");
                Thread.Sleep(1000);
            }
        }

        private static void ReceiveFile(Object socket)
        {
    
    
            Socket clientSocket = socket as Socket; //as运算符类似于强制转换操作.只是在转换失败时,as运算符会返回null,而不会引发异常。
            int BUFFERSIZE = 1024;
            try
            {
    
    

                byte[] buffer = new byte[BUFFERSIZE];
                int countReceive = clientSocket.Receive(buffer);
                string receiveStr = Encoding.Default.GetString(buffer, 0, countReceive);
                Console.WriteLine(receiveStr);
                string[] command = receiveStr.Split(',');

                string fileName = null;
                long fileLength = -1L; // 初始值为-1,L代表长整型。

                if (command[0] == "nameAndLength")
                {
    
    
                    fileName = command[1];
                    fileLength = long.Parse(command[2]);
                    clientSocket.Send(Encoding.Default.GetBytes("ok")); //  发送回应信息给发送端
                    Console.WriteLine("接收文件:" + fileName + " 请等候……");

                    long recieved = 0L;

                    using (FileStream fsWriter = new FileStream(Path.Combine(recivePath, fileName), FileMode.Create, FileAccess.Write, FileShare.None))
                    {
    
    
                        int recive;

                        while (recieved < fileLength)
                        {
    
    
                            recive = clientSocket.Receive(buffer);
                            fsWriter.Write(buffer, 0, recive);
                            fsWriter.Flush();
                            recieved += recive;
                            Console.WriteLine("已接收数据:{0}/{1}", recieved.ToString(), fileLength.ToString());
                        }

                        Console.WriteLine("接收完成……\n");
                    }
                }
            }
            catch (Exception)
            {
    
    
                Console.WriteLine("服务器端退出!!");
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/ZhangJingHuaJYO/article/details/124531893