Socket发送文件
.Net.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks; namespace SocketIM
{
////// Net : 提供静态方法,对常用的网络操作进行封装
public class Net
{
public class ObjectState
{
public string fileName { get; set; }
public Socket workSocket { get; set; }
public Thread workThread { get; set; }
}
private Net()
{
} ////// 向远程主机发送数据
//////要发送数据且已经连接到远程主机的 Socket///待发送的数据///发送数据的超时时间,以秒为单位,可以精确到微秒///0:发送数据成功;-1:超时;-2:发送数据出现错误;-3:发送数据时出现异常////// 当 outTime 指定为-1时,将一直等待直到有数据需要发送
public static int SendData(Socket socket, byte[] buffer, int outTime)
{
if (socket == null || socket.Connected == false)
{
throw new ArgumentException("参数socket 为null,或者未连接到远程计算机");
}
if (buffer == null || buffer.Length == )
{
throw new ArgumentException("参数buffer 为null ,或者长度为 0");
} int flag = ;
try
{
int totalLen = buffer.Length;
int sndLen = ; while (true)
{
if ((socket.Poll(outTime * , SelectMode.SelectWrite) == true))
{ // 收集了足够多的传出数据后开始发送
sndLen = socket.Send(buffer, sndLen, totalLen, SocketFlags.None);
totalLen -= sndLen;
if (totalLen == )
{ // 数据已经全部发送
flag = ;
break;
}
else
{
if (sndLen > )
{ // 数据部分已经被发送continue;
}
else
{ // 发送数据发生错误
flag = -;
break;
}
}
}
else
{ // 超时退出
flag = -;
break;
}
}
}
catch (SocketException e)
{ flag = -;
}
return flag;
} ////// 向远程主机发送文件
//////要发送数据且已经连接到远程主机的 socket///待发送的文件名称///文件发送时的缓冲区大小///发送缓冲区中的数据的超时时间///0:发送文件成功;-1:超时;-2:发送文件出现错误;-3:发送文件出现异常;-4:读取待发送文件发生错误////// 当 outTime 指定为-1时,将一直等待直到有数据需要发送
public static int SendFile(string ip, int port, string fileName, int maxBufferLength, int outTime)
{
IPAddress address = IPAddress.Parse(ip);
IPEndPoint endpoint = new IPEndPoint(address, port);
//创建服务端负责监听的套接字,参数(使用IPV4协议,使用流式连接,使用TCO协议传输数据)
Thread.Sleep();
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(endpoint);
if (socket.Connected)
{
Console.WriteLine(socket.RemoteEndPoint + "连接成功");
}
if (fileName == null || maxBufferLength <= )
{
throw new ArgumentException("待发送的文件名称为空或发送缓冲区的大小设置不正确.");
}
int flag = ;
try
{
FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
long fileLen = fs.Length; // 文件长度
long totalLen = fileLen; // 未读取部分
int readLen = ; // 已读取部分
byte[] buffer = null; if (fileLen <= maxBufferLength)
{ /* 文件可以一次读取*/
buffer = new byte[fileLen];
readLen = fs.Read(buffer, , (int)fileLen);
flag = SendData(socket, buffer, outTime);
}
else
{
/* 循环读取文件,并发送 */
while (totalLen != )
{
if (totalLen < maxBufferLength)
{
buffer = new byte[totalLen];
readLen = fs.Read(buffer, , Convert.ToInt32(totalLen));
}
else
{
buffer = new byte[maxBufferLength];
readLen = fs.Read(buffer, , maxBufferLength);
}
if ((flag = SendData(socket, buffer, outTime)) < )
{
break;
}
totalLen -= readLen;
}
}
fs.Flush();
fs.Close();
socket.Shutdown(SocketShutdown.Both);
socket.Close();
}
catch (IOException e)
{ flag = -;
}
if (flag == )
{
Console.WriteLine(fileName + "文件发送成功");
socket.Close();
Console.WriteLine("连接关闭");
}
else
{
Console.WriteLine(fileName + "文件发送失败,i=" + flag);
}
return flag;
}
private static void WatchConnecting(object info)
{
ObjectState state = (ObjectState)info;
Socket socketWatch = state.workSocket;
while (true)//持续不断的监听客户端的请求
{
//开始监听 客户端连接请求,注意:Accept方法,会阻断当前的线程
Socket connection = socketWatch.Accept(); if (connection.Connected)
{ //创建通信线程
Thread thradRecMsg = new Thread(RecMsg);
state.workSocket = connection;
state.workThread = thradRecMsg;
thradRecMsg.IsBackground = true;
thradRecMsg.Start(state); }
} }
////// 接收消息
private static void RecMsg(object socketClientPara)
{ ObjectState state = (ObjectState)socketClientPara;
string fileName = state.fileName;//$@"d:HQ.dat";//获得用户保存文件的路径
Socket socketClient = state.workSocket;
FileStream fs = null;
while (true)
{
//定义一个接受用的缓存区(100M字节数组)
//将接收到的数据存入arrMsgRec数组,并返回真正接受到的数据的长度
if (socketClient.Connected)
{
try
{
//因为终端每次发送文件的最大缓冲区是512字节,所以每次接收也是定义为512字节
byte[] buffer = new byte[];
int size = ;
//统计实际文件大小
long len = ;
//创建文件流,然后让文件流来根据路径创建一个文件
fs = new FileStream(fileName, FileMode.Append);
DateTime oTimeBegin = DateTime.Now;
//从终端不停的接受数据,然后写入文件里面,只到接受到的数据为0为止,则中断连接
while ((size = socketClient.Receive(buffer, , buffer.Length, SocketFlags.None)) > )
{
fs.Write(buffer, , size);
len += size;
}
DateTime oTimeEnd = DateTime.Now;
TimeSpan oTime = oTimeEnd.Subtract(oTimeBegin);
fs.Flush();
fs.Close(); socketClient.Shutdown(SocketShutdown.Both);
socketClient.Close();
Console.WriteLine("文件保存成功:" + fileName);
Console.WriteLine("接收文件用时:" + oTime.ToString() + ",文件大小:" + len / + "kb");
}
catch (Exception ex)
{
if (fs != null)
{
fs.Dispose();
}
if (File.Exists(fileName))
{
File.Delete(fileName);
}
Console.WriteLine(socketClient.RemoteEndPoint + "下线了"); break;
}
}
else
{ }
}
} public static void AcceptFile(string ip, int port, string fileName)
{
//创建服务端负责监听的套接字,参数(使用IPV4协议,使用流式连接,使用Tcp协议传输数据)
Socket socketListen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socketListen.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
//获取Ip地址对象
IPAddress address = IPAddress.Parse(ip);
//创建包含Ip和port的网络节点对象
IPEndPoint endpoint = new IPEndPoint(address, port); //将负责监听的套接字绑定到唯一的Ip和端口上
socketListen.Bind(endpoint);
//设置监听队列的长度
socketListen.Listen();
connectDone.Set();
ObjectState state = new ObjectState(); //创建负责监听的线程,并传入监听方法
Thread threadWatch = new Thread(WatchConnecting);
state.fileName = fileName;
state.workSocket = socketListen;
state.workThread = threadWatch;
threadWatch.IsBackground = true;//设置为后台线程
threadWatch.Start(state);//开始线程 }
public static void CloseTcpSocket(Thread threadWatch, Socket socketWatch)
{ threadWatch.Abort();
socketWatch.Close();
Console.WriteLine("服务器关闭监听");
}
public static ManualResetEvent connectDone = new ManualResetEvent(false);
public static void FileMove(string ip, int port, string fromPath, string toPath)
{ AcceptFile(ip, port, toPath);
connectDone.WaitOne();
int i = SendFile(ip, port, fromPath, , );
Console.WriteLine("文件从" + fromPath + "到" + toPath + "移动成功!!!!");
} }
}
.调用代码
private void button1_Click(object sender, EventArgs e)
{
//string topath = $@"d:HQ.dat";
//string frompath = $@"e:\HQ.dat";
//Net.FileMove("127.0.0.1", 11000, frompath,topath);
string topath = $@"d:bb\HQ.dat";
string frompath = $@"d:aa\HQ.dat";
Net.FileMove("127.0.0.1", , frompath, topath);
}
Socket发送文件的更多相关文章
- android开发,socket发送文件,read阻塞,得不到文件尾-1
这是我的接收文件代码:开始可以读取到-1,但是现在又读取不到了,所以才加上红色字解决的(注释的代码) File file = new File(mfilePath,"chetou." ...
- Python -- 网络编程 -- Socket发送文件
客户端如果直接send两次,一次发文件名,一次发文件内容 服务端接受的时候会一起接收,不知怎么分开发送,或者分开接收, 或者全部接收再解析内容 今天发现传送mp3文件的时候没问题,传送文本文件的话,以 ...
- python 通过 socket 发送文件
目录结构: client: #!/usr/bin/env python # -*-coding:utf-8 -*- import socket, struct, json download_dir = ...
- java socket 发送文件
客户端: package tt; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStrea ...
- socket(TCP)发送文件
一:由于在上一个随笔的基础之上拓展的所以直接上代码,客户端: using System; using System.Collections.Generic; using System.Componen ...
- C# socket 发送图片和文件
先说服务端:界面:如图: 界面设计源码 namespace SocketJPGToTxt { partial class Form1 { /// <summary> /// 必需的设计器变 ...
- socket发送文字、图片、文件---基于python实现
socket官方文档:https://docs.python.org/2/library/socket.html socket中文详细介绍:http://blog.csdn.net/rebelqsp/ ...
- C#使用FileSystemWatcher来监控指定文件夹,并使用TCP/IP协议通过Socket发送到另外指定文件夹
项目需求: 局域网内有两台电脑,电脑A(Windows系统)主要是负责接收一些文件(远程桌面粘贴.FTP上传.文件夹共享等方式),希望能在A接收文件后自动传输到电脑B(Windows系统)来做一个备份 ...
- 利用Socket远程发送文件
思想: 1.注意使用两个通道,一个普通对象通信通道,另一个纯净的文件字节流通道 2.利用通信通道发送文件请求,新建字节流通道,开始发送文件
随机推荐
- DesignPattern(四)结构型模式(下)
上篇链接 https://www.cnblogs.com/qixinbo/p/9023764.html 继续介绍最后三种结构型模式 外观模式 外观模式,也称作 ”门面“模式,在系统中,客户端经常需要 ...
- C#多线程应用:子线程更新主窗体控件的值(一)
我记得以前写过一次关于多线程的调用及更新的文章,由于时间比较久了,现在一时没找到.在做项目的时候,用到了多线程,还是有很多的同事在问多线程更新主窗体的事情,现在就这个事情做个记录. 说起多线程之间的更 ...
- python删除x天前文件及文件夹
#!/usr/bin/env python # -*- coding:utf-8 -*- import os, time, sys, shutil def delFiles(beforeSec, di ...
- IE9 下面, XMLHttpRequest 是不支持跨域请求的解决方法
在 IE9 下面, XMLHttpRequest 是不支持跨域请求的. IE10 的 XMLHttpRequest 支持跨域, 而 IE8, IE9 需要使用 XDomainRequest 来实现跨域 ...
- GCC 三
前记: 经常浏览博客园的同学应该会觉得本文有标题党之嫌,这个标题的句式来自于MiloYip大牛的大作<C++强大背后>,在此,向Milo兄致意. GCC,全称GNU Compiler Co ...
- [html] charset
UTF-8是全球通用的,GB2312一般是简体中文,GBK在他的范围上扩展了繁体中文,适合香港台湾. 页面透明效果 CSS: opacity:0.1;filter: Alpha(Opacity=10, ...
- 第13届景驰-埃森哲杯广东工业大学ACM程序设计大赛-等式(求$N^2$的因子个数)
一.题目链接 https://www.nowcoder.com/acm/contest/90/F 二.题面 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言655 ...
- jsp获取请求头信息
<%@ page language="java" import="java.util.*" contentType="text/html; ch ...
- ffmpeg重要的参考学习网址
http://lib.csdn.net/liveplay/knowledge/1586 FFmpeg滤镜使用指南 http://blog.csdn.net/fireroll/article/detai ...
- 交叉编译OpenCV的Android版本
交叉编译OpenCV的Android版本 OpenCV作为一个强大的图像处理库,在Android上也有强大的应用. OpenCV官网提供了SDK的下载,可以直接下载使用 OpenCV官网地址:http ...