首页 > 代码库 > Socket学习4 文件传输
Socket学习4 文件传输
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.IO;
using System.Xml;
namespace App_MYCS.HDL_class
{
class my_socketfile
{
private string path = "F:\\SmartMovie.EXE"; //要发送的文件
private Socket s;
private void listen()
{
string ip = "127.0.0.1"; //远程IP 这里定义为自己的机器
IPAddress[] ih = Dns.GetHostAddresses(ip); //获得IP列表
IPAddress newip = ih[0]; //获取IP地址
int port = 6789; //定义端口
IPEndPoint Conncet = new IPEndPoint(newip, port); //构造结点
s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //初始化socket
try
{
s.Connect(Conncet); //连接远程服务器
if (s.Connected) //如果连接成功 s.Connected 则为true 否则为 false
{
Console.WriteLine("连接成功");
Thread t = new Thread(new ThreadStart(set)); //创建线程
t.Start(); //开始线程
Console.WriteLine("发送完毕");
}
}catch(NullReferenceException e)
{
Console.WriteLine("{0}",e);
}
}
//创建set函数
private void set()
{
Console.WriteLine("开始发送数据");
byte[] b = new byte[10000000]; //创建文件缓冲区,这里可以认为文件的最大值
FileStream file = System.IO.File.Open(path, FileMode.Open, FileAccess.Read); //创建文件流
int start = 0;
int end = (int)file.Length; //获取文件长度 文件传送如果有需要超过int的范围估计就要改写FileStream类了
try
{
while (end != 0)
{
int count = file.Read(b, start, end); //把数据写进流
start += count;
end -= count;
}
while (start != 0)
{
int n = s.Send(b, end, start, SocketFlags.None); //用Socket的Send方法发送流
end += n;
start -= n;
}
file.Close(); //关闭文件流
s.Close(); //关闭Socket
}
catch (NullReferenceException e)
{
Console.WriteLine("{0}", e);
}
}
/*
这样文件发送的模型就实现了
接下去实现文件的接收,首先要确定对方发送文件的长度,
* 其实上面的那段还要加入发送文件长度的功能,实现很简单,
* 就是发送int变量end ,然后要求接收代码返回一个Boolean确定是否发送,
* 这里为了更简明的说清楚原理并没有实现
*/
private void get()
{
string path = "G:\\da.exe"; //接收的文件
FileStream file = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write); //写入文件流
TcpListener listen = new TcpListener(6789); //监听端口
Socket s1 = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //定义Socket并初始化
try
{
listen.Start(); //开始监听
s1 = listen.AcceptSocket(); //获取Socket连接
byte[] data = http://www.mamicode.com/new byte[10000000]; //定义缓冲区
int longer = data.Length;
int start = 0;
int mid = 0;
if (s1.Connected) //确定连接
{
Console.WriteLine("连接成功");
int count = s1.Receive(data, start, longer, SocketFlags.None); //把接收到的byte存入缓冲区
mid += count;
longer -= mid;
while (count != 0)
{
count = s1.Receive(data, mid, longer, SocketFlags.None);
mid += count;
longer -= mid;
}
file.Write(data, 0, 1214134); //写入文件,1214134为文件大小,可以用socket发送获得,代码前面已经说明。
s1.Close();
file.Close();
}
}
catch (NullReferenceException e)
{
Console.WriteLine("{0}", e);
}
}
}
class my_sockets
{
string _responseStr;
/// <summary>
/// GET方式发送请求
/// </summary>
/// <param name= "requestUrl "> 请求地址 </param>
/// <returns> 响应字符串 </returns>
public string SendRequest(string requestUrl)
{
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(requestUrl);
httpWebRequest.Method = "GET ";
WebResponse webResponse = httpWebRequest.GetResponse();
StreamReader responseStream = new StreamReader(webResponse.GetResponseStream(), System.Text.Encoding.UTF8);
_responseStr = responseStream.ReadToEnd();
webResponse.Close();
responseStream.Close();
return _responseStr;
}
/// <summary>
/// Class1 的摘要说明。
/// </summary>
// RequestState 类用于通过
// 异步调用传递数据
public class RequestState
{
const int BUFFER_SIZE = 1024;
public StringBuilder RequestData;
public byte[] BufferRead;
public HttpWebRequest Request;
public Stream ResponseStream;
// 创建适当编码类型的解码器
public Decoder StreamDecode = Encoding.Default.GetDecoder();
public RequestState()
{
BufferRead = new byte[BUFFER_SIZE];
RequestData = http://www.mamicode.com/new StringBuilder(" ");
Request = null;
ResponseStream = null;
}
}
// ClientGetAsync 发出异步请求
public static ManualResetEvent allDone = new ManualResetEvent(false);
const int BUFFER_SIZE = 1024;
public static void Main(string[] args)
{
//修改或给此字符串作循环,以连续的发送和接受数据流
string HttpUrl = "http://211.154.223.116:3000/tysy.jsp?CorpID=1&Phone=13012345678&Data=http://www.mamicode.com/17200310101";
// 从命令行获取 URI
Uri HttpSite = new Uri(HttpUrl);
// 创建请求对象
HttpWebRequest wreq = (HttpWebRequest)WebRequest.Create(HttpSite);
// 创建状态对象
RequestState rs = new RequestState();
// 将请求添加到状态,以便它可以被来回传递
rs.Request = wreq;
// 发出异步请求
IAsyncResult r = (IAsyncResult)wreq.BeginGetResponse(new AsyncCallback(RespCallback), rs);
// 将 ManualResetEvent 设置为 Wait,
// 以便在调用回调前,应用程序不退出
allDone.WaitOne();
}
private static void RespCallback(IAsyncResult ar)
{
// 从异步结果获取 RequestState 对象
RequestState rs = (RequestState) ar.AsyncState;
// 从 RequestState 获取 HttpWebRequest
HttpWebRequest req = rs.Request;
// 调用 EndGetResponse 生成 HttpWebResponse 对象
// 该对象来自上面发出的请求
HttpWebResponse resp = (HttpWebResponse) req.EndGetResponse(ar);
// 既然我们拥有了响应,就该从
// 响应流开始读取数据了
Stream ResponseStream = resp.GetResponseStream();
// 该读取操作也使用异步完成,所以我们
// 将要以 RequestState 存储流
rs.ResponseStream = ResponseStream;
// 请注意,rs.BufferRead 被传入到 BeginRead。
// 这是数据将被读入的位置。
IAsyncResult iarRead = ResponseStream.BeginRead(rs.BufferRead, 0, BUFFER_SIZE, new AsyncCallback(ReadCallBack), rs);
}
private static void ReadCallBack(IAsyncResult asyncResult)
{
// 从 asyncresult 获取 RequestState 对象
RequestState rs = (RequestState)asyncResult.AsyncState;
// 取出在 RespCallback 中设置的 ResponseStream
Stream responseStream = rs.ResponseStream;
// 此时 rs.BufferRead 中应该有一些数据。
// 读取操作将告诉我们那里是否有数据
int read = responseStream.EndRead(asyncResult);
if (read > 0)
{
// 准备 Char 数组缓冲区,用于向 Unicode 转换
Char[] charBuffer = new Char[BUFFER_SIZE];
// 将字节流转换为 Char 数组,然后转换为字符串
// len 显示多少字符被转换为 Unicode
int len = rs.StreamDecode.GetChars(rs.BufferRead, 0, read, charBuffer, 0);
String str = new String(charBuffer, 0, len);
// 将最近读取的数据追加到 RequestData stringbuilder 对象中,
// 该对象包含在 RequestState 中
rs.RequestData.Append(str);
// 现在发出另一个异步调用,读取更多的数据
// 请注意,将不断调用此过程,直到
// responseStream.EndRead 返回 -1
IAsyncResult ar = responseStream.BeginRead(rs.BufferRead, 0, BUFFER_SIZE, new AsyncCallback(ReadCallBack), rs);
}
else
{
if (rs.RequestData.Length > 1)
{
// 所有数据都已被读取,因此将其显示到控制台
string strContent;
strContent = rs.RequestData.ToString();
//Console.WriteLine(strContent.Trim().ToString());
string MsgData = "http://www.mamicode.com/Phone=" + MidStr("phone ", strContent) + "\n " + "Data= "http://www.mamicode.com/+ MidStr("data ", strContent) + "\n " + "Data-Id= " + MidStr("data-id ", strContent);
Console.WriteLine(MsgData.ToString());
//==================================以XML方式处理流时,有问题.所以我把返回值当字符串处理的==============================
// XmlNodeReader nreader = null;
// try
// {
// XmlDocument exampledoc = new XmlDocument();
// exampledoc.Load(strContent.Trim().ToString());
// XmlNode name = exampledoc.SelectSingleNode
// ( "/csjx-service/data "); ///单个读取节点值
// if(name!= null)
// {
// nreader = new XmlNodeReader(name);
// while(nreader.Read())
// {
// Console.Write (nreader.Value);
// Console.Write (nreader.Name+ " ");
// }
// }
// }
// finally
// {
// if(nreader!=null)
// nreader.Close();
// }
}
// 关闭响应流
responseStream.Close();
// 设置 ManualResetEvent,以便主线程可以退出
allDone.Set();
}
return;
}
/// <summary>
/// 返回两个字符串节点之间的字符串
/// </summary>
/// <param name= "NodeStr "> 字符节点 </param>
/// <param name= "StreamStr "> 数据流 </param>
/// <returns> 返回的提取的字符串 </returns>
public static string MidStr(string NodeStr, string StreamStr)
{
int StarStr = (StreamStr.Trim()).IndexOf(" < " + NodeStr.Trim() + "> ");
int StopStr = (StreamStr.Trim()).IndexOf(" </ " + NodeStr.Trim() + "> ");
string MidStr = (StreamStr.Trim()).Substring(StarStr + NodeStr.Length + 2, StopStr - StarStr - NodeStr.Length - 2);
return MidStr;
}
}
}
Socket学习4 文件传输