.net Socket 网络编程(五)
来源:互联网 发布:备份应用的软件 编辑:程序博客网 时间:2024/05/22 12:16
在(四)中已经实现了简单的客户端,服务器端的异步数据传输。
现在让我们继续完善功能实现文件的上传
客户端部分
修改文件流,在头部添加8个字节位置保存实际文件字节长度
修改AsyncConnect方法
//开始异步连接
public void AsyncConnect()
...{
try
...{
InitIPInfo();
Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
serverSocket.BeginConnect(ipEndPoint, new AsyncCallback(ConnectCallback), serverSocket);
connectDone.WaitOne(); //阻止运行直到连接成功
//发送数据
FileStream fs = new FileStream(_file, FileMode.Open);
byte[] buffer = new byte[fs.Length];
fs.Read(buffer, 0, (int)fs.Length);
long fileLen = fs.Length;
byte[] bufferFile = BitConverter.GetBytes(fileLen);
buffer = ComBineArray<byte>(bufferFile, buffer);
Console.WriteLine("共有很数据 {0} bytes 需要发送,其中文件大小 {1} bytes",buffer.Length,bufferFile.Length);
serverSocket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(SendCallback), serverSocket);
sendDone.WaitOne();
StateObject state = new StateObject();
state.workSocket = serverSocket;
serverSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize, SocketFlags.None, new AsyncCallback(ReceiveCallback), state);
receiveDone.WaitOne();
Console.WriteLine("接收到服务器信息:{0}", response);
serverSocket.Shutdown(SocketShutdown.Both);
serverSocket.Close();
}
catch(Exception ex)
...{
Console.WriteLine("发生异常"+ex.Message);
}
}
public void AsyncConnect()
...{
try
...{
InitIPInfo();
Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
serverSocket.BeginConnect(ipEndPoint, new AsyncCallback(ConnectCallback), serverSocket);
connectDone.WaitOne(); //阻止运行直到连接成功
//发送数据
FileStream fs = new FileStream(_file, FileMode.Open);
byte[] buffer = new byte[fs.Length];
fs.Read(buffer, 0, (int)fs.Length);
long fileLen = fs.Length;
byte[] bufferFile = BitConverter.GetBytes(fileLen);
buffer = ComBineArray<byte>(bufferFile, buffer);
Console.WriteLine("共有很数据 {0} bytes 需要发送,其中文件大小 {1} bytes",buffer.Length,bufferFile.Length);
serverSocket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(SendCallback), serverSocket);
sendDone.WaitOne();
StateObject state = new StateObject();
state.workSocket = serverSocket;
serverSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize, SocketFlags.None, new AsyncCallback(ReceiveCallback), state);
receiveDone.WaitOne();
Console.WriteLine("接收到服务器信息:{0}", response);
serverSocket.Shutdown(SocketShutdown.Both);
serverSocket.Close();
}
catch(Exception ex)
...{
Console.WriteLine("发生异常"+ex.Message);
}
}
这是用来联合两个byte数组的方法
private static T[] ComBineArray<T>(T[] a1, T[] a2)
...{
T[] result = new T[a1.Length + a2.Length];
int a1Len = Buffer.ByteLength(a1);
int a2Len = Buffer.ByteLength(a2);
Buffer.BlockCopy(a1, 0, result, 0, a1Len);
Buffer.BlockCopy(a2, 0, result, a1Len, a2Len);
return result;
}
...{
T[] result = new T[a1.Length + a2.Length];
int a1Len = Buffer.ByteLength(a1);
int a2Len = Buffer.ByteLength(a2);
Buffer.BlockCopy(a1, 0, result, 0, a1Len);
Buffer.BlockCopy(a2, 0, result, a1Len, a2Len);
return result;
}
服务器部分
在异步acceptCallback方法中修改第一次读取的字节数
private void acceptCallback(IAsyncResult ar)
...{
Console.WriteLine("acceptCallback 被调用");
Socket listener = (Socket)ar.AsyncState;
Socket clientSocket = listener.EndAccept(ar); //获得客户端套接字接口
Console.WriteLine("建立连接");
allDone.Set();
StateObject state = new StateObject();
state.WorkSocket = clientSocket;
// 第一次调用先取8个字节
clientSocket.BeginReceive(state.buffer, 0, 8, SocketFlags.None, new AsyncCallback(readCallback), state); //开始接受数据
}
...{
Console.WriteLine("acceptCallback 被调用");
Socket listener = (Socket)ar.AsyncState;
Socket clientSocket = listener.EndAccept(ar); //获得客户端套接字接口
Console.WriteLine("建立连接");
allDone.Set();
StateObject state = new StateObject();
state.WorkSocket = clientSocket;
// 第一次调用先取8个字节
clientSocket.BeginReceive(state.buffer, 0, 8, SocketFlags.None, new AsyncCallback(readCallback), state); //开始接受数据
}
修改readCallback方法
public void readCallback(IAsyncResult ar)
...{
StateObject state = (StateObject)ar.AsyncState;
Socket clientSocket = state.WorkSocket;
try
...{
int read = 0;
read = clientSocket.EndReceive(ar);//结束挂起的异步读取
Console.WriteLine("获得字节{0}bytes",read);
if (read > 0)
...{
if (read == 8 && totalBytes == 0) //获得文件长度标识
...{
totalBytes += read;
fileBytes = BitConverter.ToInt64(state.buffer, 0);
clientSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize, SocketFlags.None, new AsyncCallback(readCallback), state);
}
else
...{
totalBytes += read;
if (read != StateObject.BufferSize)
...{
byte[] resultBytes = new byte[read];
Buffer.BlockCopy(state.buffer, 0, resultBytes, 0, (int)read);
state.totalBuffer = ComBineArray<byte>(state.totalBuffer, resultBytes);
}
else
...{
state.totalBuffer = ComBineArray<byte>(state.totalBuffer, state.buffer);
}
if (totalBytes == fileBytes + 8)
...{
Console.WriteLine("已经接收完数据,共{0}bytes,最后一批{1}bytes",state.totalBuffer.Length,state.buffer.Length);
//保存文件
CreateFile(state.totalBuffer);
//回复客户端
byte[] backBuffer = new byte[1024];
string backString = "文件上传完成";
backBuffer = Encoding.GetEncoding("gb2312").GetBytes(backString);
clientSocket.BeginSend(backBuffer, 0, backBuffer.Length, SocketFlags.None, new AsyncCallback(SendCallback), state);
}
else
...{
clientSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize, SocketFlags.None, new AsyncCallback(readCallback), state);
}
}
}
}
catch (SocketException se)
...{
if (se.ErrorCode == 10054)
...{
Console.WriteLine("客户端已断开连接!");
}
else
...{
Console.WriteLine(se.Message);
}
}
catch (Exception ex)
...{
Console.WriteLine(ex.Message);
}
}
...{
StateObject state = (StateObject)ar.AsyncState;
Socket clientSocket = state.WorkSocket;
try
...{
int read = 0;
read = clientSocket.EndReceive(ar);//结束挂起的异步读取
Console.WriteLine("获得字节{0}bytes",read);
if (read > 0)
...{
if (read == 8 && totalBytes == 0) //获得文件长度标识
...{
totalBytes += read;
fileBytes = BitConverter.ToInt64(state.buffer, 0);
clientSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize, SocketFlags.None, new AsyncCallback(readCallback), state);
}
else
...{
totalBytes += read;
if (read != StateObject.BufferSize)
...{
byte[] resultBytes = new byte[read];
Buffer.BlockCopy(state.buffer, 0, resultBytes, 0, (int)read);
state.totalBuffer = ComBineArray<byte>(state.totalBuffer, resultBytes);
}
else
...{
state.totalBuffer = ComBineArray<byte>(state.totalBuffer, state.buffer);
}
if (totalBytes == fileBytes + 8)
...{
Console.WriteLine("已经接收完数据,共{0}bytes,最后一批{1}bytes",state.totalBuffer.Length,state.buffer.Length);
//保存文件
CreateFile(state.totalBuffer);
//回复客户端
byte[] backBuffer = new byte[1024];
string backString = "文件上传完成";
backBuffer = Encoding.GetEncoding("gb2312").GetBytes(backString);
clientSocket.BeginSend(backBuffer, 0, backBuffer.Length, SocketFlags.None, new AsyncCallback(SendCallback), state);
}
else
...{
clientSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize, SocketFlags.None, new AsyncCallback(readCallback), state);
}
}
}
}
catch (SocketException se)
...{
if (se.ErrorCode == 10054)
...{
Console.WriteLine("客户端已断开连接!");
}
else
...{
Console.WriteLine(se.Message);
}
}
catch (Exception ex)
...{
Console.WriteLine(ex.Message);
}
}
创建新文件方法
private void CreateFile(byte[] bytes)
...{
string fileName = "aaOnServer.txt";
string filePath = Path.Combine(Application.StartupPath, fileName);
FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write);
BinaryWriter bw = new BinaryWriter(fs);
bw.Write(bytes);
bw.Close();
fs.Close();
}
...{
string fileName = "aaOnServer.txt";
string filePath = Path.Combine(Application.StartupPath, fileName);
FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write);
BinaryWriter bw = new BinaryWriter(fs);
bw.Write(bytes);
bw.Close();
fs.Close();
}
- .net Socket 网络编程(五)
- Java Socket网络编程五
- .net Socket 网络编程(一)
- .net Socket 网络编程(二)
- .net Socket 网络编程(三)
- .net Socket 网络编程(四)
- Linux内核开发五:Socket网络编程
- .net网络编程之一:Socket编程
- .net网络编程之一:Socket编程
- [C#] .net网络编程之一:Socket编程
- .net网络编程之一:Socket编程
- .net网络编程之一:Socket编程
- .net网络编程之一:Socket编程
- .net网络编程之一:Socket编程
- .net网络编程之一:Socket编程【转】
- .net网络编程之一:Socket编程
- .net网络编程之一:Socket编程
- Java网络编程学习笔记(五)客户端Socket
- 面试题:统计整数的二进制形式1的个数
- tomahawk JSF组件扩展组件(一)
- 百度IM名字与界面首度曝光
- 数据库管理员
- 让你的Java程序只有一个进程实例在运行
- .net Socket 网络编程(五)
- 没想到我也会用唇膏
- 奇怪的BIRT数据集问题
- js未结束的字符串常量解决方案之一。。
- 开通博客
- Multi-Threading & others
- 面向对象方法
- 字符串匹配算法研究(一)
- 世界上最短的DVD解码程序