服务器端: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Net.Sockets; using System.Threading; using System.Runtime.InteropServices; using System.IO; namespace RecvFileServer { /// <summary> /// 本文件主要处理多文件传输,首先做单文件传输,然后做多文件进行传输,今天完成对多文件发送.今天一定要写完成对多文件传输.能够进行测试成功 /// </summary> [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] struct SendFileMessage { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public char [] fileName; /// <summary> /// 传递的包类型。1 代表发送要创建的文件,2. 代表为第一条数据,但不是最后一条数据 3. 为中间传输数据,并非为最后一个,4. 代表文件最后一条数据 5. 第一条也是最后一条文件数据 /// 1. 首先能够实现基本的单文件传输,单文件传输以后,便可以实现基本的多文件传输。 /// </summary> public char typeMessage; //有效数据长度 public int effDataLength; //有效数据 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)] public byte [] effData; } public class StateObject { // Client socket. public Socket workSocket = null ; // Size of receive buffer. public const int BufferSize = 1037; // Receive buffer. public byte [] buffer = new byte [BufferSize]; //在此处,每个socket有对应额的一个FileStream } public class AsynchronousSocketServer { public static FileStream writefile; public static ManualResetEvent allDone = new ManualResetEvent( false ); private static Socket serverSocket; public static void StartAsynchronousSocket() { Console.WriteLine( "服务器启动成功" ); IPAddress ipAddress = IPAddress.Parse( "192.168.0.40" ); IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 8083); serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { serverSocket.Bind(ipEndPoint); serverSocket.Listen(1000); while ( true ) { allDone.Reset(); serverSocket.BeginAccept( new AsyncCallback(AcceptCallback), serverSocket); allDone.WaitOne(); } } catch (System.Exception ex) { Console.WriteLine(ex.Message); } } public static void AcceptCallback(IAsyncResult ar) { //在此处输出连接到的ip地址。当连接成功的时候,进行接收数据。handle指代的是连接到的client的socket Socket listener = (Socket)ar.AsyncState; Socket handler = listener.EndAccept(ar); allDone.Set(); StateObject states = new StateObject(); states.workSocket = handler; handler.BeginReceive(states.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(RecvCallback), states); } public static void RecvCallback(IAsyncResult ar) { //在此处进行设置一下,将其中的放入进去 String content = String.Empty; //获取StateObject实例,并获取StateObject中的socket StateObject state = (StateObject)ar.AsyncState; Socket handler = state.workSocket; //从client socket接收数据 int bytesRead = handler.EndReceive(ar); if (bytesRead > 0) { //判断读写的数据是否完成。如果没有,继续读写,如何判断是否接受完成呢?不能够使用EOF呢 if (bytesRead == 1037) { //获取传输到的数据,并转为Unicode字符,以便支持中文.在此处进行开始获取得到的数据,然后将获取到的数据转变为结构体类型 SendFileMessage sfm = new SendFileMessage(); sfm = (SendFileMessage)ByteToStruct(state.buffer, typeof (SendFileMessage)); Console.WriteLine(sfm.typeMessage); //此处暂时把1去掉,改用在读取第一次的时候进行创建 if (sfm.typeMessage == '1' ) { } else if (sfm.typeMessage == '2' ) //2 代表的是文件对应的第一次,需要打开对应的文件,是否需要在SocketState中进行呢? { //每个客户端的连接可以的,依次放入其中呢。对每个客户进行的连接,我们都需要设置并将其中的连接放入到里面。现在都先放入debug文件目录下 String strPath = new String(sfm.fileName); writefile = new FileStream(strPath + ".jpg" , FileMode.OpenOrCreate); writefile.Write(sfm.effData, 0, sfm.effDataLength); } else if (sfm.typeMessage == '3' ) { //如何根据其中的设置来进行。重新写发送部分,先能够成功接收一张<1K,=1K,>1K的文件; writefile.Write(sfm.effData, 0, sfm.effDataLength); } else if (sfm.typeMessage == '4' ) { //代表最后一段数据,接受后写入到文件中,然后将文件关闭.每次打开后关闭,打开后关闭.在此处判断并将设置出来 writefile.Write(sfm.effData, 0, sfm.effDataLength); writefile.Close(); } else if (sfm.typeMessage == '5' ) { //如果此处为5代表文件大小小于1024字节,可以打开文件并进行存储.打开文件,把获取到的数据保存到新建的文件夹中.在此处接收成功。 //单文件进行传输,并将文件放入到里面 string strPath = new String(sfm.fileName); writefile = new FileStream(strPath + ".jpg" , FileMode.OpenOrCreate); writefile.Write(sfm.effData, 0, sfm.effDataLength); writefile.Close(); } } } //使用异步接收,继续接收数据,将接收到的数据写入到文件中去,并将数据放入文件中去。成功接收两张图片。一个是<1024,一个是>1024并且余数!=0 handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(RecvCallback), state); } public static byte [] StructToBytes( object structObj, int size) { int len = Marshal.SizeOf(structObj); byte [] bytes = new byte [size]; IntPtr structPtr = Marshal.AllocHGlobal(size); //将结构体拷到分配好的内存空间。 Marshal.StructureToPtr(structObj, structPtr, false ); //从内存空间拷贝到byte 数组欧拉模型外的另一种相机模型UVN系统。编写 Marshal.Copy(structPtr, bytes, 0, size); //释放内存空间,为每个部分做大量的要求,并把其中的要求放入进去,背面消除方式。FreeHGlobal. Marshal.FreeHGlobal(structPtr); return bytes; } public static object ByteToStruct( byte [] bytes, Type type) { int size = Marshal.SizeOf(type); if (size > bytes.Length) { return null ; } //分配结构体空间,并把结构体AllocHGlobal(size); IntPtr structPtr = Marshal.AllocHGlobal(size); //将byte数组拷贝到分配好的内存空间 Marshal.Copy(bytes, 0, structPtr, size); //将内存空间转换为目标结构体 object obj = Marshal.PtrToStructure(structPtr, type); //释放内存空间。 Marshal.FreeHGlobal(structPtr); return obj; } } } |
客户端:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using System.Runtime.InteropServices;
namespace SendFileClient
{
[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
struct SendFileMessage
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public char[] fileName;
//传递的包类型。1 代表发送要创建的文件,2. 代表为第一条数据 3. 为中间传输数据,并非为最后一个,4. 代表文件最后一条数据 5.第一条也是最后一条文件数据
public char typeMessage;
//有效数据长度
public int effDataLength;
//有效数据
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)]
public byte[] effData;
}
class AsynchronousSocketClient
{
public static ManualResetEvent allDone = new ManualResetEvent(false);
public static Socket client;
public static void StartAsynchronousSocket()
{
IPAddress ipAddress = IPAddress.Parse(“192.168.0.40”);
IPEndPoint ipPoint = new IPEndPoint(ipAddress, 8083);
client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
client.BeginConnect(ipPoint, new AsyncCallback(ConnectCallBack), client);
allDone.WaitOne();
while (true)
{
allDone.Reset();
SendFile(client, “zhl.jpg”, “20101112”);
SendFile(client, “jnvc.jpg”, “20101113”);
allDone.WaitOne();
}
}
public static void ConnectCallBack(IAsyncResult args)
{
Socket client = (Socket)args.AsyncState;
client.EndConnect(args);
Console.WriteLine(“Socket connected to {0}”, client.RemoteEndPoint.ToString());
allDone.Set();
}
public static void Send(Socket handler, String data)
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.Unicode.GetBytes(data);
// Begin sending the data to the remote device.此处发生错误?是否是因为其进行呢??
handler.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), handler);
}
public static void Send(Socket handler, byte[] byteData)
{
handler.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), handler);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
Socket handler = (Socket)ar.AsyncState;
int bytesSent = handler.EndSend(ar);
Console.WriteLine(“Sent {0} bytes to server.”, bytesSent);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
public static void SendFile(Socket client, String filePath,String serverFileName)
{
byte[] sendByteMessage = new byte[1037];
FileInfo fileInfo = new FileInfo(filePath);
int fileSize = (int)(fileInfo.Length);
FileStream afile = new FileStream(filePath, FileMode.Open);
SendFileMessage sfm = new SendFileMessage();
byte[] sendDataByte = new byte[1037];
byte[] dataByte = new byte[1024];
int i = (int)fileSize / 1024;
int yu = (int)fileSize % 1024;
//< = 1024 byte,则一次性把文件发送到服务器端
//>1024 byte的 时候,余数为0和不为0的情况,如果余数为0
if (fileSize <= 1024)
{
//在此处写入到2.jpg
afile.Seek(0, SeekOrigin.Begin);
afile.Read(dataByte, 0, fileSize);
sfm.effData = dataByte;
sfm.effDataLength = fileSize;
sfm.fileName = (serverFileName.ToCharArray());
sfm.typeMessage = ‘5’;
sendDataByte = StructToBytes(sfm, 1037);
Send(client, sendDataByte);
afile.Close();
}
else
{
if (yu != 0)
{
//余数不为0,则把其中的数据放入其中
for (int j = 0; j < i; j++)
{
//重新为sendByteMessage赋值。文件数据大小必须要符合要求。不然会报错。使用光照引擎来进行
sfm.fileName = serverFileName.ToCharArray();
if (j == 0)
{
sfm.typeMessage = ‘2’;
sfm.fileName = serverFileName.ToCharArray();
sfm.effDataLength = 1024;
}
else
sfm.typeMessage = ‘3’;
afile.Seek(j * 1024, SeekOrigin.Begin);
afile.Read(dataByte, 0, 1024);
sfm.effData = dataByte;
sendByteMessage = StructToBytes(sfm,1037);
Send(client, sendByteMessage);
//全部数据发送。一定是要再接收数据.判断其中的数据,放入到里面中
}
int seekNum = i * 1024;
long operNum = (long)seekNum;
afile.Seek(operNum, SeekOrigin.Begin);
afile.Read(dataByte, 0, yu);
//在此处重新组合sfm,然后发送次文件到sfm
sfm.typeMessage=’4′;
//在此处要把sfm转变为struct类型
sendByteMessage = StructToBytes(sfm, 1037);
Send(client, sendByteMessage);
afile.Close();
}
else
{
for (int j = 0; j < i; j++)
{
afile.Seek(j * 1024, SeekOrigin.Begin);
afile.Read(dataByte, 0, 1024);
}
afile.Close();
}
}
}
private static void AsynchronousFileSendCallback(IAsyncResult ar)
{
Socket client = (Socket)ar.AsyncState;
client.EndSendFile(ar);
}
//当时怎么做的呢?的确是呢,可以呢?
public static byte[] StructToBytes(object structObj, int size)
{
int len = Marshal.SizeOf(structObj);
byte[] bytes = new byte[size];
IntPtr structPtr = Marshal.AllocHGlobal(size);
//将结构体拷到分配好的内存空间
Marshal.StructureToPtr(structObj, structPtr, false);
//从内存空间拷贝到byte数组
Marshal.Copy(structPtr, bytes, 0, size);
//释放内存空间,基于8bit
Marshal.FreeHGlobal(structPtr);
return bytes;
}
public static object ByteToStruct(byte[] bytes, Type type)
{
int size = Marshal.SizeOf(type);
if (size > bytes.Length)
{
return null;
}
//分配结构体
IntPtr structPtr = Marshal.AllocHGlobal(size);
//将byte数组拷贝到分配好的内存空间
Marshal.Copy(bytes, 0, structPtr, size);
//将内存空间转换为目标结构体
object obj = Marshal.PtrToStructure(structPtr,type);
//释放内存空间 定向光源和点光源
Marshal.FreeHGlobal(structPtr);
return obj;
}
}
}
来源URL:http://www.cnblogs.com/sdnyzhl/archive/2013/05/20/3088207.html