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