C#实战026:socket实现单文件传输

    实现简单的信息通信,接下来我们要继续来是实现文件的传输,同样这次先试试单个简单的小文件传输,首先先说说原理,这次我们先对文件进行文件名获取,将文件名以信息传输的形式的先传递给服务端,目的是让服务器知道我们要发送的文件名及文件类型,接着再来发送文件,这里我们需要将文件转化成字节形式发送,然后再把接收到的字节写入到文件中。

这里用到了Forms窗口程序来获取需要传送的文件,大家可以参考:C#实战025:控制台调用Forms窗口程序

客户端代码(已经详细的解释了每行代码的意思了):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using System.Windows.Forms;


namespace SocketClient
{
    class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            SocketClient();
        }
        public static string serverIp = "127.0.0.1";//设置服务端IP
        public static int serverPort = 8888;//服务端端口
        public static Socket socketClient;//定义socket
        public static Thread threadClient;//定义线程
        public static byte[] result = new byte[1024];//定义缓存
        public static void SocketClient()
        {
            socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//创建一个socket的对象
            IPAddress ip = IPAddress.Parse(serverIp);//获取服务器IP地址
            IPEndPoint point = new IPEndPoint(ip, serverPort);//获取端口
            try
            {
                socketClient.Connect(point);//链接服务器IP与端口
                Console.WriteLine("连接服务器中.....");
            }
            catch (Exception)
            {
                Console.WriteLine("与服务器链接失败!!!");
                return;
            }
            Console.WriteLine("与服务器链接成功!!!");
            try
            {
                Thread.Sleep(1000);    //等待1秒钟  
                //通过 socketClient 向服务器发送数据
                string sendMessage = "已成功接到SocketClient发送的消息";//发送到服务端的内容
                byte[] send = Encoding.UTF8.GetBytes(sendMessage);//Encoding.UTF8.GetBytes()将要发送的字符串转换成UTF8字节数组
                byte[] SendMsg = new byte[send.Length + 1];//定义新的字节数组
                SendMsg[0] = 0;//将数组第一位设置为0,来表示发送的是消息数据  
                Buffer.BlockCopy(send, 0, SendMsg, 1, send.Length);//偏移复制字节数组
                socketClient.Send(SendMsg);  //将接受成功的消息返回给SocketServer服务器 
                Console.WriteLine("发送完毕:{0}", sendMessage);
            }
            catch
            {
                socketClient.Shutdown(SocketShutdown.Both);//禁止Socket上的发送和接受
                socketClient.Close();//关闭Socket并释放资源
            }
            try
            {
                OpenFileDialog open = new OpenFileDialog();//创建OpenFileDialog实例,方便打开选取文件对话框
                open.Multiselect = true;//是否允许多选
                if (open.ShowDialog() == DialogResult.OK)//按下确定选择的按钮
                {
                    string fileName = open.FileName;  //获取选取文件的文件路径及文件名
                    FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);//创建文件流,用来读取数据
                    string fileN = Path.GetFileName(fileName);//提取文件名
                    byte[] arrMsg = Encoding.UTF8.GetBytes(fileN);//将要发送的字符串转换成UTF8字节数组
                    byte[] arrSendMsg = new byte[arrMsg.Length + 1];//定义新的字节数组
                    arrSendMsg[0] = 0;//将数组第一位设置为0,来表示发送的是消息数据  
                    Buffer.BlockCopy(arrMsg, 0, arrSendMsg, 1, arrMsg.Length);//偏移复制字节数组
                    socketClient.Send(arrSendMsg); //将接受成功的消息返回给SocketServer服务器 
                    byte[] arrFile = new byte[fs.Length]; //定义缓存控件,长度为文件长度
                    int length = fs.Read(arrFile, 0, arrFile.Length);//将文件读入缓存空间
                    byte[] SendarrFile = new byte[length + 1];//定义新的字节数组
                    SendarrFile[0] = 1;//将数组第一位设置为1,来表示发送的是文件数据
                    Buffer.BlockCopy(arrFile, 0, SendarrFile, 1, length);//偏移复制字节数组
                    socketClient.Send(SendarrFile);//将读取成功的文件发送给SocketServer服务器 
                    Console.WriteLine("文件发送完毕!!!!");
                }
            }
            catch (Exception)
            {
                socketClient.Shutdown(SocketShutdown.Both);//禁止Socket上的发送和接受
                socketClient.Close();//关闭Socket并释放资源
            }
            socketClient.Close();//关闭Socket并释放资源
            Console.ReadLine();
        }
    }

}

服务器端代码(已经详细的解释了每行代码的意思了): 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using System.Windows.Forms;

namespace SocketServer
{
    class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            SocketServer();
        }
        public static string serverIp = "127.0.0.1";//设置服务端IP
        public static int serverPort = 8888;//服务端端口
        public static Socket socketServer;//定义socket
        public static Thread threadWatch;//定义线程
        public static byte[] result = new byte[1024 * 1024 * 2];//定义缓存
        public static string fileName;//获取文件名
        public static void SocketServer()
        {
            socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//创建一个socket的对象
            IPAddress ip = IPAddress.Parse(serverIp);//获取服务器IP地址
            IPEndPoint point = new IPEndPoint(ip, serverPort);//获取端口
            try
            {
                socketServer.Bind(point);//绑定IP地址及端口
            }
            catch (Exception ex)
            {
                Console.WriteLine("绑定IP时出现异常:" + ex.Message);
                return;
            }
            socketServer.Listen(100);//开启监听并设定最多10个排队连接请求
            threadWatch = new Thread(WatchConnect);//创建一个监听进程
            threadWatch.IsBackground = true;//后台启动
            threadWatch.Start();//运行
            Console.WriteLine("服务器{0}监听启动成功!", socketServer.LocalEndPoint.ToString());
            Console.ReadLine();
        }
        public static void WatchConnect()
        {
            while (true)
            {
                Socket watchConnect = socketServer.Accept();//接收连接并返回一个新的Socket
                watchConnect.Send(Encoding.UTF8.GetBytes("服务器连接成功"));//在客户端显示"服务器连接成功"提示
                Thread threadwhat = new Thread(ReceiveMsg);//创建一个接受信息的进程
                threadwhat.IsBackground = true;//后台启动
                threadwhat.Start(watchConnect);//有传入参数的线程
            }
        }
        public static void ReceiveMsg(object watchConnect)
        {
            Socket socketClient = (Socket)watchConnect;
            while (true)
            {
                int num = -1;//初始化num
                string reveiceName;//定义字符串
                try
                {
                    num = socketClient.Receive(result);//获取客户端信息
                    reveiceName = Encoding.UTF8.GetString(result, 0, num);//把从0到num的字节变成String
                }
                catch (SocketException ex)
                {
                    Console.WriteLine("异常:" + ex.Message + ", RemoteEndPoint: " + socketClient.RemoteEndPoint.ToString());
                    break;
                }
                catch (Exception ex)
                {
                    Console.WriteLine("异常:" + ex.Message);
                    break;
                }
                try
                {
                    if (reveiceName[0] == 0)//判断数组第一个值,如果为0则说明传的是信息
                    {
                        fileName = Encoding.UTF8.GetString(result, 1, num - 1);//提取字节信息并转换成String
                        Console.WriteLine("接收客户端的消息:{0}", fileName);
                    }
                    if (reveiceName[0] == 1)//判断数组第一个值,如果为0则说明传的是文件
                    {
                        SaveFileDialog save = new SaveFileDialog();//创建SaveFileDialog实例
                        string spath = @"C:\Users\admin\Desktop";//制定存储路径
                        string fullPath = Path.Combine(spath, fileName);//获取存储路径及文件名
                        FileStream filesave = new FileStream(fullPath, FileMode.Create, FileAccess.Write);//创建文件流,用来写入数据
                        filesave.Write(result, 1, num - 1);//将数据写入到文件中
                        filesave.Close();
                        Console.WriteLine("保存成功!!!");
                    }
                }
                catch (Exception ex )
                {

                    Console.WriteLine(ex.Message );
                }
              
            }
            
        }
    }
}

猜你喜欢

转载自blog.csdn.net/kevinfan2011/article/details/84675414