文件传输_文件传输协议 - CSDN
  • Socket实现文件传输

    万次阅读 2018-07-25 18:12:24
    Socket实现文件传输 1.客户端 通过new Socket("ip",port)连接服务端 创建文件输入流读取文件 创建返回套接字的输出流 写入文章名称,长度等属性 读取、写入文章操作 关闭流 package com.company;...

    Socket实现文件传输

    1.客户端

    通过new Socket("ip",port)连接服务端

    创建文件输入流读取文件

    创建返回套接字的输出流

    写入文章名称,长度等属性

    读取、写入文章操作

    关闭流

    package com.company;
    
    import javax.xml.crypto.Data;
    import java.io.*;
    import java.net.Socket;
    
    //客户端
    public class Client extends Socket{
    	private  final String SERVER_IP="192.168.201.104";
    	private final int SERVER_PORT=8999;
    	private Socket client;
    	private FileInputStream fis;
    	private DataOutputStream dos;
    
    	//创建客户端,并指定接收的服务端IP和端口号
    	public Client() throws IOException{
    		this.client=new Socket(SERVER_IP,SERVER_PORT);
    		System.out.println("成功连接服务端..."+SERVER_IP);
    	}
    
    	//向服务端传输文件
    	public void sendFile(String url) throws IOException {
    		File file=new File(url);
    		try {
    			 fis = new FileInputStream(file);
    			//BufferedInputStream bi=new BufferedInputStream(new InputStreamReader(new FileInputStream(file),"GBK"));
    			dos = new DataOutputStream(client.getOutputStream());//client.getOutputStream()返回此套接字的输出流
    			//文件名、大小等属性
    			dos.writeUTF(file.getName());
    			dos.flush();
    			dos.writeLong(file.length());
    			dos.flush();
    			// 开始传输文件
    			System.out.println("======== 开始传输文件 ========");
    			byte[] bytes = new byte[1024];
    			int length = 0;
    			
    			while ((length = fis.read(bytes, 0, bytes.length)) != -1) {
    				dos.write(bytes, 0, length);
    				dos.flush();
    			}
    			System.out.println("======== 文件传输成功 ========");
    		}catch(IOException e){
    			e.printStackTrace();
    			System.out.println("客户端文件传输异常");
    		}finally{
    			fis.close();
    			dos.close();
    		}
    	}
    	public static void main(String[] args) {
    		try {
    			Client client = new Client(); // 启动客户端连接
    			client.sendFile("E:/dxn/aaa.txt"); // 传输文件
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    }
    
    

    2服务端

    启动服务端new ServerSocket(port)

    接收连接服务端的客户端对象

    创建返回套接字的输入流

    创建文件输出流写出文件

    读取文章名称,长度等属性

    读取、写入文章操作

    关闭流

    package com.company;
    
    import java.io.*;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class FileServer extends ServerSocket{
    
            private static final int SERVER_PORT = 8999; // 服务端端口
            private ServerSocket server;
            private Socket socket;
            private DataInputStream dis;
            private FileOutputStream fos;
    
            public FileServer() throws Exception {
                server=new ServerSocket(SERVER_PORT);
            }
    
            public void task() throws IOException{
                System.out.println("======== 等待连接 ========");
                Socket socket = server.accept();
                System.out.println(" Ip:"+socket.getInetAddress()+"已连接");
                try {
                    dis = new DataInputStream(socket.getInputStream());
                    // 文件名和长度
                    String fileName = dis.readUTF();
                    long fileLength = dis.readLong();
                    File directory = new File("E:/a");
                    if(!directory.exists()) {
                        directory.mkdir();
                    }
                    File file = new File(directory.getAbsolutePath() + File.separatorChar + fileName);
    
                    fos = new FileOutputStream(file);
                    System.out.println("file。。。。。。。。。。。。。。"+file);
                    System.out.println("fileName。。。。。。。。。。。。。。"+fileName);
    
                    System.out.println("======== 开始接收文件 ========");
                    byte[] bytes = new byte[1024];
                    int length = 0;
                    while((length = dis.read(bytes, 0, bytes.length)) != -1) {
                        fos.write(bytes, 0, length);
                        fos.flush();
                    }
    
                    System.out.println("======== 文件接收成功 ========");
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        try {
                            if(fos != null)
                                fos.close();
                            if(dis != null)
                                dis.close();
                            socket.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
    
            public static void main(String[] args) {
                try {
                    FileServer server = new FileServer(); // 启动服务端
                    server.task();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    
    

    3. 每接收到一个Socket就建立一个新的线程来处理它

    package com.company;
    
    
    import java.io.DataInputStream;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class Server extends ServerSocket {
    
    	private static final int SERVER_PORT = 8999; // 服务端端口
    
    	private ServerSocket server;
    
    	public Server() throws Exception {
    		server=new ServerSocket(SERVER_PORT);
    	}
    
    	/**
    	 * 使用线程处理每个客户端传输的文件
    	 * @throws Exception
    	 */
    	public void load() throws Exception {
    		while (true) {
    			System.out.println("-----------等待连接-------- ");
    			Socket socket = server.accept();//接收连接服务端的客户端对象
    			System.out.println("ip" + socket.getInetAddress() + "已连接");
    			new Thread(new Transfer(socket),"thread1").start();// 每接收到一个Socket就建立一个新的线程来处理它
    			System.out.println(Thread.currentThread().getName());
    		}
    	}
    
    	/**
    	 * 处理客户端传输过来的文件线程类
    	 */
    	class Transfer implements Runnable {
    
    		private Socket socket;
    		private DataInputStream dis;
    		private FileOutputStream fos;
    
    		public Transfer(Socket socket) {
    			this.socket = socket;
    		}
    
    		@Override
    		public void run() {
    			try {
    				dis = new DataInputStream(socket.getInputStream());
    
    				// 文件名和长度
    				String fileName = dis.readUTF();
    				long fileLength = dis.readLong();
    				File directory = new File("E:/xn");
    				if(!directory.exists()) {
    					directory.mkdir();
    				}
    				File file = new File(directory.getAbsolutePath() + File.separatorChar + fileName);
    				System.out.println("file"+file);
    				fos = new FileOutputStream(file);
    
    				// 开始接收文件
    				byte[] bytes = new byte[1024];
    				int length = 0;
    				while((length = dis.read(bytes, 0, bytes.length)) != -1) {
    					fos.write(bytes, 0, length);
    					fos.flush();
    				}
    				System.out.println("======== 文件接收成功 [File Name:" + fileName + "] ");
    			} catch (Exception e) {
    				e.printStackTrace();
    			} finally {
    				try {
    					if(fos != null)
    						fos.close();
    					if(dis != null)
    						dis.close();
    
    				} catch (Exception e) {
    					e.printStackTrace();
    				}
    			}
    		}
    	}
    	public static void main(String[] args) {
    		try {
    			Server server = new Server(); // 启动服务端
    			server.load();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    }
    
    
    

     4.DataInputStream:数据输入流     读取基本 Java 数据类型

    DataOutputStream:数据输出流      写出基本 Java 数据类型

     

     

    展开全文
  • 使用TCP协议实现文件传输

    千次阅读 2013-01-17 15:54:42
    使用TCP协议实现文件传输。程序会分为服务器端和客户端,首先运行服务器端,监听来自客户端的连接,客户端运行后会通过程序内的服务器端IP地址,向服务器发送连接请求。双方建立请求之后,客户端将所需文件的文件名...

    使用TCP协议实现文件传输。程序会分为服务器端和客户端,首先运行服务器端,监听来自客户端的连接,客户端运行后会通过程序内的服务器端IP地址,向服务器发送连接请求。双方建立请求之后,客户端将所需文件的文件名和绝对路径传输给服务器,如果服务器找到此文件,则将此文件传输给客户端,然后断开连接。

    具体算法描述如下:

    【1】服务器端:

    1、初始化socket服务

    2、监听连接请求并做相应的处理

    2.1创建监听套接字

    2.2监听套接口

    2.3接受套接字的连接

    2.4接收客户端传来的数据

    case 文件绝对路径:

    按照路径找到文件,并打开。提取本地文件名,发回给客户端

    发送文件总长度给客户端

    case 已准备接收文件完毕

    if 发送缓冲区为空

    读取文件,写入缓冲区

    将文件流分成大小相同的组(最后一组可能会小一点),顺次发送给客户端

    将缓冲区清空

    case 文件成功传送

    打印消息,退出

    case 文件已存在

    打印消息,退出

    2.5关闭同客户端的连接

    3、释放socket服务

    【2】客户端:

    1、初始化socket,winsock服务

    2、连接服务器,进行数据的传输

    2.1初始化,创建套接字

    2.2通过IP地址,向服务器发送连接请求,建立连接

    2.3主动发送所求文件绝对路径

    2.4接受服务器端数据并做相应处理

    case 打开文件错误:

    重新发送文件绝对路径至服务器,请求重发

    case 文件长度:

    打印消息

    case 文件名:

    if 文件已经存在

    发送“文件已经存在”

    else

    分配缓冲区,并向服务器发送“Ready”消息

    case 文件流:

    为已接收文件名创建文件

    打开文件,将文件流数据写入文件,直至接收所有分组数据

    发送“成功接收“消息

    3、关闭套接字

    释放服务

    源程序:

    【1】服务器端:

    头文件:

    /*server.h*/
    #pragma comment(lib, "WS2_32")
    #include <WinSock2.h>
    #include <iostream>
    #include <assert.h>
    #include<Windows.h>
    #ifndef COMMONDEF_H
    #define COMMONDEF_H
    #define MAX_PACKET_SIZE   10240    // 数据包的最大长度,单位是sizeof(char)
    #define MAXFILEDIRLENGTH 256     // 存放文件路径的最大长度
    #define PORT     4096    // 端口号
    //#define SERVER_IP    "127.0.0.1" // server端的IP地址
    // 各种消息的宏定义
    #define INVALID_MSG      -1   // 无效的消息标识
    #define MSG_FILENAME     1   // 文件的名称
    #define MSG_FILELENGTH     2   // 传送文件的长度
    #define MSG_CLIENT_READY    3   // 客户端准备接收文件
    #define MSG_FILE      4   // 传送文件
    #define MSG_SENDFILESUCCESS    5   // 传送文件成功
    #define MSG_OPENFILE_ERROR    10   // 打开文件失败,可能是文件路径错误找不到文件等原因
    #define MSG_FILEALREADYEXIT_ERROR 11   // 要保存的文件已经存在了
    class CCSDef
    {
    public:
    #pragma pack(1)      // 使结构体的数据按照1字节来对齐,省空间
    // 消息头
    struct TMSG_HEADER
    {
       char    cMsgID;    // 消息标识
       TMSG_HEADER(char MsgID = INVALID_MSG)
        : cMsgID(MsgID)
       {
       }
    };
    // 请求传送的文件名
    // 客户端传给服务器端的是全路径名称
    // 服务器传回给客户端的是文件名
    struct TMSG_FILENAME : public TMSG_HEADER
    {
       char szFileName[256];   // 保存文件名的字符数组
       TMSG_FILENAME()
        : TMSG_HEADER(MSG_FILENAME)
       {
       }
    };
    // 传送文件长度
    struct TMSG_FILELENGTH : public TMSG_HEADER
    {
       long lLength;
       TMSG_FILELENGTH(long length)
        : TMSG_HEADER(MSG_FILELENGTH), lLength(length) 
       {
       }
    };
    // Client端已经准备好了,要求Server端开始传送文件
    struct TMSG_CLIENT_READY : public TMSG_HEADER
    {
       TMSG_CLIENT_READY()
        : TMSG_HEADER(MSG_CLIENT_READY)
       {
       }
    };
    // 传送文件
    struct TMSG_FILE : public TMSG_HEADER
    {
       union     // 采用union保证了数据包的大小不大于MAX_PACKET_SIZE * sizeof(char)
       {
        char szBuff[MAX_PACKET_SIZE];
        struct
        {
         int nStart;
         int nSize;
         char szBuff[MAX_PACKET_SIZE - 2 * sizeof(int)];
        }tFile;
       };
       TMSG_FILE()
        : TMSG_HEADER(MSG_FILE)
       {
       }
    };
    // 传送文件成功
    struct TMSG_SENDFILESUCCESS : public TMSG_HEADER
    {
       TMSG_SENDFILESUCCESS()
        : TMSG_HEADER(MSG_SENDFILESUCCESS)
       {
       }
    };
    // 传送出错信息,包括:
    // MSG_OPENFILE_ERROR:打开文件失败
    // MSG_FILEALREADYEXIT_ERROR:要保存的文件已经存在了
    struct TMSG_ERROR_MSG : public TMSG_HEADER
    {
       TMSG_ERROR_MSG(char cErrorMsg)
        : TMSG_HEADER(cErrorMsg)
       {
       }
    };
    #pragma pack()
    };
    #endif
    

    cpp文件:

    /*Server.cpp*/
    #include"Server.h"
    char g_szNewFileName[MAXFILEDIRLENGTH];
    char g_szBuff[MAX_PACKET_SIZE + 1];
    long g_lLength;
    char* g_pBuff = NULL;
    //初始化socket库
    bool InitSocket();
    //关闭socket库
    bool CloseSocket();
    //解析消息并进行相应的处理
    bool ProcessMsg(SOCKET sClient);
    //监听Client消息
    void ListenToClient();
    //打开文件
    bool OpenFile(CCSDef::TMSG_HEADER* pMagHeader,SOCKET sClient);
    //传送文件
    bool SendFile(SOCKET sClient);
    //读取文件进缓冲区
    bool ReadFile(SOCKET sClient);
    
    int main()
    {
    	while(1)
    	{
    		InitSocket();
    		ListenToClient();
    		CloseSocket();
    		system("del E:\\test1.A_exp");
    	}
    		//system("pause");
    	return 0;
    }
    
    //初始化socket库
    bool InitSocket()
    {
    	WSADATA wsaData;
    	WORD socketVersion=MAKEWORD(2,2);
    	if(::WSAStartup(socketVersion,&wsaData)!=0)
    	{//初始化WinSock服务
    		printf("Init socket dll error\n");
    		return false;
    	}
    	return true;
    }
    //关闭socket库
    bool CloseSocket()
    {//释放winsock库
    	::WSACleanup();
    	if(g_pBuff != NULL)
    	{
    		delete [] g_pBuff;
    		g_pBuff = NULL;
    	}
    	return true;
    }
    //解析消息并进行相应的处理
    bool ProcessMsg(SOCKET sClient)
    {
    	//从套接口中接收数据,返回copy的字节数
    	int nRecv = ::recv(sClient,g_szBuff,MAX_PACKET_SIZE+1,0);
    	if(nRecv>0)
    	{
    		g_szBuff[nRecv]='\0';
    	}
    	//解析命令
    	CCSDef::TMSG_HEADER* pMsgHeader=(CCSDef::TMSG_HEADER*)g_szBuff;
    
    	switch(pMsgHeader->cMsgID)
    	{
    	case MSG_FILENAME://文件名
    		{
    			OpenFile(pMsgHeader,sClient);
    		}
    		break;
    	case MSG_CLIENT_READY://客户端已准备完毕,开始传送文件
    		{
    			SendFile(sClient);
    		}
    		break;
    	case MSG_SENDFILESUCCESS://传送文件成功
    		{
    			printf("Send File Success!\n");
    			return false;
    		}
    		break;
    	case MSG_FILEALREADYEXIT_ERROR://要保存的文件已经存在
    		{
    			printf("The file ready to send already exit!\n");
    			return false;
    		}
    		break;
    	}
    	return true;
    }
    //监听Client消息
    void ListenToClient()
    {
    	//创建套接字
    	SOCKET sListen = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    	if(sListen == SOCKET_ERROR)
    	{
    		printf("Init Socket Error!\n");
    		return;
    	}
    	//绑定socket
    	sockaddr_in sin;
    	sin.sin_family=AF_INET;
    	sin.sin_port=htons(PORT);
    	sin.sin_addr.S_un.S_addr=INADDR_ANY;
    	if (::bind(sListen, (LPSOCKADDR)&sin, sizeof(sockaddr_in)) == SOCKET_ERROR)
    	{
    	   printf("Bind Error!\n");
    	   return;
    	}
    	// 设置socket进入监听状态
    	if(::listen(sListen,10)==SOCKET_ERROR)
    	{
    		printf("Listen Error!\n");
    		return;
    	}
    	printf("Listening To Client...\n");
    	//循环接收client端的连接请求
    	sockaddr_in ClientAddr;
    	int nAddrLen = sizeof(sockaddr_in);
    	SOCKET sClient;
    	//取队列最前端客户连接请求,创建套接字连接通道
    	while((sClient=::accept(sListen,(sockaddr*)&ClientAddr,&nAddrLen))==INVALID_SOCKET)
    	{}
    	//解析消息并进行相应的处理
    	//int count=10;//作为定时当程序执行10s未完成时直接退出
    	//while(ProcessMsg(sClient)==true&&count>0)
    	//{
    	//	Sleep(1000);
    	//	count--;
    	//}
    	while(ProcessMsg(sClient)==true)
    	{
    		Sleep(1000);
    	}
    	//关闭同客户端的连接
    	::closesocket(sClient);
    	::closesocket(sListen);
    }
    //打开文件
    bool OpenFile(CCSDef::TMSG_HEADER* pMsgHeader,SOCKET sClient)
    {
    	CCSDef::TMSG_FILENAME* pRequstFileNameMsg=(CCSDef::TMSG_FILENAME*)pMsgHeader;
    	//对文件名进行处理
    	char *p1,*p2;
    	for(p1=pRequstFileNameMsg->szFileName,p2=g_szNewFileName;*p1!='\0';p1++,p2++)
    	{
    		if(*p1!='\n')
    		{
    			*p2=*p1;
    		}
    		if(*p2=='\\')//将‘\’转换为‘\\’
    		{
    			*(++p2)='\\';
    		}
    	}
    	*p2='\0';
    	ReadFile(sClient);
    	return true;
    }
    //传送文件
    bool SendFile(SOCKET sClient)
    {
    	if (NULL == g_pBuff)
    	{//如果缓冲区为空
    	   ReadFile(sClient);
    	}
    	int nPacketBufferSize = MAX_PACKET_SIZE - 2 * sizeof(int); // 每个数据包存放文件的buffer大小
    	// 如果文件的长度大于每个数据包所能传送的buffer长度那么就分块传送
    	for (int i = 0; i < g_lLength; i += nPacketBufferSize)
    	{  
    	   CCSDef::TMSG_FILE tMsgFile;
    	   tMsgFile.tFile.nStart = i;
    	   if (i + nPacketBufferSize + 1> g_lLength)
    	   {//文件块已经是最后一块
    		tMsgFile.tFile.nSize = g_lLength - i;
    	   }
    	   else
    	   {
    		tMsgFile.tFile.nSize = nPacketBufferSize;
    	   }
    	   memcpy(tMsgFile.tFile.szBuff, g_pBuff + tMsgFile.tFile.nStart, tMsgFile.tFile.nSize);//copy到缓冲区
    	   ::send(sClient, (char*)(&tMsgFile), sizeof(CCSDef::TMSG_FILE), 0);
    	   Sleep(0.5);
    	}
    	delete [] g_pBuff;
    	g_pBuff = NULL;
    	return true;
    }
    //读取文件进缓冲区
    bool ReadFile(SOCKET sClient)
    {
    	if(g_pBuff!=NULL)
    	{//如果缓冲区不为空
    		return true;
    	}
    	//打开文件
    	FILE *pFile;
    	if((pFile = fopen(g_szNewFileName, "rb"))==NULL)
    	{//文件打开失败,发送错误报告
    		 printf("Cannot find the file, request the client input file name again\n");
    		 CCSDef::TMSG_ERROR_MSG tMsgErrorMsg(MSG_OPENFILE_ERROR);
    		 ::send(sClient, (char*)(&tMsgErrorMsg), sizeof(CCSDef::TMSG_ERROR_MSG), 0);
    		 return false;
    	}
    	//传送文件长度到Client
    	fseek(pFile,0,SEEK_END);//重定位指针到文件末尾
    	g_lLength=ftell(pFile);//返回文件指针相对于文件头的偏移量
    	printf("File Length = %d\n", g_lLength);
    	CCSDef::TMSG_FILELENGTH tMsgFileLength(g_lLength);
    	::send(sClient,(char*)(&tMsgFileLength), sizeof(CCSDef::TMSG_FILELENGTH), 0);
    	// 处理文件全路径名,把文件名分解出来
    	//磁盘号,目录,文件名,后缀名
    	char szDrive[_MAX_DRIVE], szDir[_MAX_DIR], szFname[_MAX_FNAME], szExt[_MAX_EXT];
    	_splitpath(g_szNewFileName, szDrive, szDir, szFname, szExt);
    	strcat(szFname,szExt);
    	CCSDef::TMSG_FILENAME tMsgFileName;
    	strcpy(tMsgFileName.szFileName, szFname);
    	printf("Send File Name: %s\n", tMsgFileName.szFileName);
    	::send(sClient, (char*)(&tMsgFileName), sizeof(CCSDef::TMSG_FILENAME), 0);
    	//分配缓冲区,读取文件内容
    	g_pBuff = new char[g_lLength + 1];
    	if (g_pBuff == NULL)
    	{
    	   return false;
    	}
    	fseek(pFile, 0, SEEK_SET);
    	fread(g_pBuff, sizeof(char), g_lLength, pFile);
    	g_pBuff[g_lLength] = '\0';
    	fclose(pFile);
    	return true;
    }

    【2】客户端:

    头文件同服务器端头文件

    源程序文件:

    /*Client.cpp*/
    #include"Client.h"
    long g_lLength = 0;
    char* g_pBuff = NULL;
    char g_szFileName[MAXFILEDIRLENGTH];
    char g_szBuff[MAX_PACKET_SIZE+1];
    SOCKET g_sClient;
    // 初始化socket库
    bool InitSocket();
    // 关闭socket库
    bool CloseSocket();
    // 把用户输入的文件路径传送到server端
    bool SendFileNameToServer();
    // 与server端连接
    bool ConectToServer();
    // 打开文件失败
    bool OpenFileError(CCSDef::TMSG_HEADER *pMsgHeader);
    // 分配空间以便写入文件
    bool AllocateMemoryForFile(CCSDef::TMSG_HEADER *pMsgHeader);
    // 写入文件
    bool WriteToFile(CCSDef::TMSG_HEADER *pMsgHeader);
    // 处理server端传送过来的消息
    bool ProcessMsg();
    
    int main()
    {
    	while(1)
    	{
    		InitSocket();
    		ConectToServer();
    		CloseSocket();
    	}
    	//system("pause");
    	return 0;
    }
    
    // 初始化socket库
    bool InitSocket()
    {
    	//初始化SOCKET
    	WSADATA wsaData;
    	WORD socketVersion=MAKEWORD(2,2);
    	if(::WSAStartup(socketVersion,&wsaData)!=0)
    	{
    		printf("Init socket dll error\n");
    		exit(-1);
    	}
    	return true;
    }
    // 关闭socket库
    bool CloseSocket()
    {
    	// 关闭套接字
    	::closesocket(g_sClient);
    	// 释放winsock库
    	::WSACleanup();
    	return true;
    }
    // 把用户输入的文件路径传送到server端
    bool SendFileNameToServer()
    {
    	char szFileName[MAXFILEDIRLENGTH];
    	printf("Input the File Directory: ");
    	//fgets(szFileName, MAXFILEDIRLENGTH, stdin);
    	strcpy(szFileName,"E:\\test1.A_exp");
    	// 把文件路径发到server端
    	CCSDef::TMSG_FILENAME tMsgRequestFileName;
    	strcpy(tMsgRequestFileName.szFileName, szFileName);
    	if (::send(g_sClient, (char*)(&tMsgRequestFileName), sizeof(CCSDef::TMSG_FILENAME), 0) == SOCKET_ERROR)
    	{
    	   printf("Send File Name Error!\n");
    	   exit(-1);
    }
    return true;
    }
    // 与server端连接
    bool ConectToServer()
    {
    	// 初始化socket套接字
    	if ((g_sClient = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == SOCKET_ERROR)
    	{
    	   printf("Init Socket Error!\n");
    	   exit(-1);
    	}
    	sockaddr_in servAddr;
    	servAddr.sin_family = AF_INET;
    	servAddr.sin_port = htons(PORT);
    	servAddr.sin_addr.S_un.S_addr = ::inet_addr(SERVER_IP);
    	if ((::connect(g_sClient, (sockaddr*)&servAddr, sizeof(sockaddr_in))) == INVALID_SOCKET)
    	{
    	   printf("Connect to Server Error!\n");
    	   exit(-1);
    	}
    	// 输入文件路径传输到server端
    	SendFileNameToServer();
    	// 接收server端传过来的信息,直到保存文件成功为止
    	while (ProcessMsg() == true)
    	{
    		Sleep(1000);
    	}
    	return true;
    }
    // 打开文件失败
    bool OpenFileError(CCSDef::TMSG_HEADER *pMsgHeader)
    {
    	if (g_pBuff != NULL)//如果缓冲区内有数据
    	   return true;
    	assert(pMsgHeader != NULL);
    	printf("Cannot find file!\n");
    	// 重新输入文件名称
    	SendFileNameToServer();
    	return true;
    }
    // 分配空间以便写入文件
    bool AllocateMemoryForFile(CCSDef::TMSG_HEADER *pMsgHeader)
    {
    	assert(pMsgHeader != NULL);
    	if (g_pBuff != NULL)
    	{
    	   return true;
    	}
    	CCSDef::TMSG_FILENAME* pRequestFilenameMsg = (CCSDef::TMSG_FILENAME*)pMsgHeader;
    	printf("File Name: %s\n", pRequestFilenameMsg->szFileName);
    	// 把文件的路径设置为D盘根目录下
    	strcpy(g_szFileName, "D:\\");
    	strcat(g_szFileName, "test2.B_imp");
    	//strcat(g_szFileName, pRequestFilenameMsg->szFileName);
    	// 查找相同文件名的文件是否已经存在,如果存在报错退出
    	FILE* pFile;
    	if ((pFile = fopen(g_szFileName, "r")) != NULL)
    	{
    	   // 文件已经存在,要求重新输入一个文件
    	   printf("The file already exist!\n");
    	   CCSDef::TMSG_ERROR_MSG tMsgErrorMsg(MSG_FILEALREADYEXIT_ERROR);
    	   ::send(g_sClient, (char*)(&tMsgErrorMsg), sizeof(CCSDef::TMSG_ERROR_MSG), 0);
    	   fclose(pFile);
    	   return false;
    	}
    	// 分配缓冲区开始接收文件,如果分配成功就给server端发送开始传送文件的要求
    	g_pBuff = new char[g_lLength + 1];
    	if (g_pBuff != NULL)
    	{
    	   memset(g_pBuff, '\0', g_lLength + 1);
    	   printf("Now ready to get the file %s!\n", pRequestFilenameMsg->szFileName);
    	   CCSDef::TMSG_CLIENT_READY tMsgClientReady;
    	   if (::send(g_sClient, (char*)(&tMsgClientReady), sizeof(CCSDef::TMSG_CLIENT_READY), 0) == SOCKET_ERROR)
    	   {
    		printf("Send Error!\n");
    		exit(-1);
    	   }
    	}
    	else
    	{
    	   printf("Alloc memory for file error!\n");
    	   exit(-1);
    	}
    	return true;
    }
    // 写入文件
    bool WriteToFile(CCSDef::TMSG_HEADER *pMsgHeader)
    {
    	assert(pMsgHeader != NULL);
    	CCSDef::TMSG_FILE* pMsgFile = (CCSDef::TMSG_FILE*)pMsgHeader;
    	int nStart = pMsgFile->tFile.nStart;
    	int nSize = pMsgFile->tFile.nSize;
    	memcpy(g_pBuff + nStart, pMsgFile->tFile.szBuff, nSize);
    	if (nStart == 0)
    	{
    	   printf("Saving file into buffer...\n");
    	}
    	memcpy(g_pBuff + nStart, pMsgFile->tFile.szBuff, nSize);
    	
    	// 如果已经保存到缓冲区完毕就写入文件
    	if (nStart + nSize >= g_lLength)
    	{
    	   printf("Writing to disk....\n");
    	   // 写入文件
    	   FILE* pFile;
    	   pFile = fopen(g_szFileName, "w+b");
    	   fwrite(g_pBuff, sizeof(char), g_lLength, pFile);
    	   delete [] g_pBuff;
    	   g_pBuff = NULL;
    	   fclose(pFile);
    	   // 保存文件成功传送消息给server退出server
    	   CCSDef::TMSG_SENDFILESUCCESS tMsgSendFileSuccess;
    	   while (::send(g_sClient, (char*)(&tMsgSendFileSuccess), sizeof(CCSDef::TMSG_SENDFILESUCCESS), 0) == SOCKET_ERROR)
    	   {
    	   }
    	   printf("Save the file %s success!\n", g_szFileName);
    	   return true;
    	}
    	else
    	{
    	   return false;
    	}
    }
    // 处理server端传送过来的消息
    bool ProcessMsg()
    {
    	CCSDef::TMSG_HEADER *pMsgHeader;
    	int nRecv = ::recv(g_sClient, g_szBuff, MAX_PACKET_SIZE + 1, 0);
    
    	pMsgHeader = (CCSDef::TMSG_HEADER*)g_szBuff;
    	switch (pMsgHeader->cMsgID)
    	{
    	case MSG_OPENFILE_ERROR:   // 打开文件错误
    	   {
    		OpenFileError(pMsgHeader);
    	   }
    	   break;
    	case MSG_FILELENGTH:    // 文件的长度
    	   {
    		if (g_lLength == 0)
    		{
    		 g_lLength = ((CCSDef::TMSG_FILELENGTH*)pMsgHeader)->lLength;
    		 printf("File Length: %d\n", g_lLength);
    		}
    	   }
    	   break;
    	case MSG_FILENAME:     // 文件名
    	   {
    		return AllocateMemoryForFile(pMsgHeader);
    	   }
    	   break;
    	case MSG_FILE:      // 传送文件,写入文件成功之后退出这个函数
    	   {
    		if (WriteToFile(pMsgHeader))
    		{
    			/*Sleep(1000);*/
    		 return false;
    		}
    	   }
    	   break;
    	}
    	return true;
    }


    展开全文
  • C++实现网络文件传输

    热门讨论 2020-07-29 14:18:51
    C++实现多线程网络文件传输
  • PPT演示文稿等文件传输,中经常使用视频和图像,因此这些类型的媒体文件附件也较大; 企业大文件跨国传输(因网络环境问题,常规的传输方式不适合大文件跨国传输); 企业的数据量急剧增长,海量数据分发与收集...

    如今,发送数GB大小的文件变得越来越普遍,影视行业传输需求,单个图像可以高达几十MB,而常规视频可超过100MB;

    PPT演示文稿等文件传输,中经常使用视频和图像,因此这些类型的媒体文件附件也较大;

    企业大文件跨国传输(因网络环境问题,常规的传输方式不适合大文件跨国传输);

    企业的数据量急剧增长,海量数据分发与收集传输需求;
    ……

    常用的大文件传输方式及优缺点:

    1.大文件如何传输—电子邮件

    电子邮件大家非常熟悉,优点方便快捷不必多说,缺点是附件大小比较有限制。例如,当前主要的电子邮件提供商如Gmail,QQ Mail和网易邮件等将其限制设置为50 MB,超大附件发送则限制在2G,且无法保证2G的文件传输成功。

    因为,即使电子邮件发送可支持50 MB,接收方邮件文件大小限制可能比此小得多。事实是,大多数电子邮件提供商最多只能支持10 MB。

    因此,如果通过电子邮件发送大文件,例如.ISO,虚拟机,高清视频,程序安装程序或放置在zip文件中的大量文档,这些文件每个可以达到数百MB或几GB,你必须将它们分成许多小部分。整个文件传输过程将非常繁琐且耗时。此外,该方法极易受到人为错误的影响。

    2.大文件如何传输—FTP

    FTP可以用于共享文件,用户将文件上传到FTP服务器,其他用户可以登录服务器并下载相关文件。FTP不限制上传文件大小,可使用它通过Internet发送大型文件。

    缺点是传输速度依然太慢,在电影行业,1小时无压缩视频文件最高可达3TB。这大约是3,000GB。通过FTP连接(45 Mbps)传输可能需要大约一周的时间才能完成,跨国传输的高延迟和数据包丢失可能会迫使45 Mbps连接产生仅5 Mbps的实际吞吐量。如果发生这种情况,它可以将你的一周文件传输转换为几个月。

    安全性较差,FTP以明文传输数据。因此,熟练的黑客可以进行中间人攻击,获取你的登录凭据,然后使用它们来访问你的FTP服务器帐户。 

    3.大文件如何传输—云网盘文件共享

    基于云的文件共享,百度云盘、360云盘、联想企业网盘等等,轻松方便。

    缺点是有上传限制,比如单个文件4GB、文件数量不能超过500个。同时你不知道文件的副本实际存储在哪里,是否会在数据中心备份,数据保护安全性较弱。

    大多数文件传输方法(包括FTP和云解决方案)都容易受到不良网络条件的影响。这就是为什么有些企业在传输大文件时干脆选择邮寄硬盘,但是现在有更好的解决方案—镭速传输

    4.大文件如何传输—镭速传输

    镭速加密传输,不受距离、文件大小和网络条件影响,传输速度可比FTP快100倍,解决安全性和传输效率的问题。
    部署简单,最快30秒安装完毕,纯软件解决方案。对应不同的传输需求和场景有不同的解决方案,镭速为华为,完美世界,万达集团等提供了高速传输解决方案。 前往试用>>

    镭速传输采用C/S模式,服务器端搭建在企业自己的服务器上,数据存储在企业自身服务器上。在传输过程中,采用UDP传输+TCP校验,AES-128数据加密,提高传企业输效率,在网络环境不好的情况下,UDP传输相对于TCP传输具有更高的适用性。

    展开全文
  • 在木马中文件管理的重要性,是无需质疑的,对于文件的管理,做到并不难,但做好却也不易在我们编写一个功能完整的“文件木马”其实现效果如图所示。为了文章的完整性,我们将分为数篇来介绍,本文主要介绍程序的整体...
    在木马中文件管理的重要性,是无需质疑的,对于文件的管理,做到并不难,但做好却也不易在我们编写一个功能完整的“文件木马”
    其实现效果如图所示。为了文章的完整性,我们将分为数篇来介绍,本文主要介绍程序的整体框架和界面实现,在以后的文章中将以此框架为基础实现详细的功能。


    编写环境

    程序的编写环境为VC6.0+WINDOWS2000 除界面外的其它部分如,程序框架,功能实现 大多用API实现所以若要移值到其它环境还是比较方便的。


    实现目标

    在开始工作前,先明确目得和方向,这样可以避免少走弯路,我们的目标主要有:枚举磁盘,枚举目录,获取文件信息
    上传文件,下载文件,执行文件,创建目录,删除目录等



    传输控制结构


    要实现客户端与服务端的通信,设计一个合理的传输控制结构,会使后面的工作轻松很多,为了使代码易读
    首先对要使用的命令进行预定义其各个命令定义如下

    #define GetDriver 0x01 //磁盘信息
    #define GetDirInfo 0x02 //目录信息
    #define ExecFile 0x03 //执行文件
    #define GetFile 0x04 //下载文件
    #define PutFile 0x05 //上传文件
    #define DelFile 0x06 //删除文件
    #define DelDir 0x07 //删除目录
    #define CreateDir 0x08 //创建目录
    #define FileInfo 0x09 //文件信息
    #define GetScreen 0x10 //查看屏幕


    在程序的网络通信中主要有 操作命令 ,命令对像,和具体数据三部分,对于命令的传输定义如下结构

    typedef struct
    {
    int ID; //操作命令
    BYTE lparam[BUF_LEN*2]; //命令对像

    }COMMAND;


    因为在程序中打交道最多的就是文件,对文件的详细属性定义如下结构


    typedef struct
    {
    char FileName[MAX_PATH]; //文件名称
    int FileLen; //文件长度
    char Time[50]; //时间信息
    BOOL IsDir; //为目录否
    BOOL Error; //错误信息
    HICON hIcon; //图标句柄

    }FILEINFO;








    服务端结构




    服务端还是比较简单的其整体思路如下


    1.服务端循环接受连接,并把连接交给线程处理
    2.线程接受"命令数据",并跟据命令ID将命令对像和SOCKET句柄传给处理函数
    3.函数执行指定功能,并返回执行结果

    对整体结构的描述,我们用伪代码表述如下

    main()
    { /*初示化设置......*/

    while(true)
    {
    if(client=accept(server,(sockaddr *)&clientaddr,&len))//循环接受连接
    {
    CreateThread(NULL,NULL,SLisen,(LPVOID)client,NULL,NULL);//传递线程处理
    }
    }
    /*清理释放资源......*/

    WSACleanup();
    }

    服务端程序运行后循环接受连接,如果有新的连接就传递给新的线程处理,线程代码如下

    DWORD WINAPI SLisen(LPVOID lparam)
    {
    SOCKET client=(SOCKET)lparam;
    COMMAND command;
    while(1)
    {
    if(recv(client,(char*)&command,sizeof(command),0)==SOCKET_ERROR)//接受命令数据
    {
    cout<<"The Clinet Socket is Closed/n";
    break;
    }else
    {
    switch(command.ID)//判断命令ID
    {
    case GetDriver://将命令对像和SOCKET句柄传递给处理函数
        GetDriverProc (command,client);
        break;
    case DelFile:
        DelFileProc (command,client);
        break;
    /*其它命令......*/
    }
    }
    }
    }

    线程式的功能是接受客户端的"命令数据",并跟跟据命令ID 将命令对像传递给处理函数,由函数完成指定的功能
    以删除文件命令为例其函数格式如下

    DWORD DelFileProc (COMMAND command,SOCKET client)
    {
    if(DeleteFile((char*)command.lparam)==0)//command.lparam为命令对像,这里为要删除的文件路径
    {
    send(client,"删除失败...");
    }
    else
    {
    send(client,"删除成功...");
    }
    }

    很容易看出,处理函数接受"命令对像"和客户端SOCKET句柄,执行后会把结果传递回去....







    客户端结构


    客户端结构的实现思路如下

    1.跟服务端建立连接
    2.发送用户命令
    3.启动一个线程,用于接受服务端的返回信息

    对整体结构的描述,我们用伪代码表述如下

    void CMyDlg::OnConnect()
    {
    if(connect(server,(SOCKADDR*)&serveraddr,sizeof(serveraddr))<0)//连接....
    {
    return ;
    }
    CreateThread(NULL,NULL,CLisen,this,NULL,NULL);//创建线程用于接受SERVER返回信息
    }


    对于用户发送的命令我们仍以删除文件为例说明其代码如下

    void CMyDlg::OnMenuDelFile()
    {
    HTREEITEM CurrentNode =   m_tree.GetSelectedItem(); //取得选择的节点
    CString FullPath =GetFullPath(CurrentNode); //取得节点全目录
    COMMAND command;
    command.ID=DelFile; //设置命令为删除文件 //删除文件
    command.lparam=FullPath.LockBuffer()); //将路径加入命令对像
    send(server,command);
    }


    用于接受SERVER返回信息的线程,和服务端接受命令线程相似,这里就不再说明了,有兴趣可以看下源代码

    到这里程序的流程框架就介绍完了,下面我们再看一下程序的界面设置.


    界面实现

    程序的主界面如上图所示,主程序是一个对话框,主要包括一个树控件m_tree和列表控件m_list分别
    用于显示磁盘目录和文件,在对话框初示化时用以下代码设置树控件的属性

    DWORD dwStyle = GetWindowLong(m_tree.m_hWnd,GWL_STYLE);
    dwStyle |=TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT;
    SetWindowLong(m_tree.m_hWnd,GWL_STYLE,dwStyle);

    对于列表框控件则没有太多要求,要留意的是,如果显示图标应该把Styles显示属性设置为ICON

    VC的做出的界面,常常让人有种摔键盘的冲动。其实稍微留意一下其设置,也可以让它漂亮一些
    比如上图所示的界面就是经过简单设置得到的,而没有用其它类库,有点兴趣?其设置方法为:

    1.在对话框属性中设置Styles 的Border属性为Thin
    2.选重More Styles "可见" 属性
    3.选重Extended Styles的"静态边"属性

    这样再运行一下程序是不是感觉清新不少?

    到这里程序的主要结构框架和界面实现就介绍完了,下一篇将详细介绍其各种功能的实现
    展开全文
  • 文件传输系统

    2020-07-30 23:31:48
    基于TDP、UDP的文件传输系统,使用C++编写 ; 基于TDP、UDP的文件传输系统,使用Java编写 ;
  • 互联网大文件传输方式

    千次阅读 2019-06-25 14:02:21
    特别是一些企业级的用户,经常会需要传输一些大型文件给别人,比如一些视频音频,庞大的数据信息,较大的应用程序,游戏等等,但是又不知道该如何发送大文件,下面将会介绍几种不同的传输文件的方式。 QQ传输 ...
  • 文件传输

    2018-04-12 21:40:10
    文件归档,就是把多个文件变成一个归档文件 2.tar c ##创建  f ##指定归档文件名称  t ##显示归档文件中的内容  r ##向归档文件中添加文件  --get ##取出单个文件  --delete ##删除单个文件  x ##取出...
  • 快速实现大文件传输你了解多少?

    千次阅读 2018-09-08 17:57:50
    方方面面的行业都要涉及到大文件传输。例如影视行业需要每天进行视频素材的传输,一个视频小至几十兆,多至几T的视频数据要从拍摄地传输到视频中心。又或者气象行业的各地气象观测点需要实时进行气象观测,即时有效...
  • 文件传输作为日常生活、工作中需求量较高的一项功能,工作中总会遇到需要将文件从一个设备转移到另一个设备上查看、存储,或者将资料回传的情况。一般大小的文件可以用QQ或者微信的文件传输助手来解决,或者任意一个...
  • 怎么远程传输文件

    万次阅读 2019-06-27 18:02:32
    虽然网络通信技术不断发展,对大数据量,高频次,远距离的文件传输成为我们工作中常常遇到的问题。常用的QQ文件传输,微信发送,邮箱,FTP等常规方式,都要面对一方发送,一方接收,或者提前上传到服务器,然后接收...
  • MAC间文件传输

    万次阅读 2018-02-04 21:53:22
    由于是在同一个局域网下,所以我们可以使用终端的远程连接来进行文件传输。 首先要先对两台mac进行共享设置:进入系统偏好设置,选择共享,启用远程登陆: 然后打开终端,输入命令连接一下目标设备看一下是否能...
  • JAVA文件传输程序

    千次阅读 2013-05-13 09:42:24
     本项任务要开发一款P2P文件传输软件,该软件可以在局域网和互连上使用,具有文件传输,断点续,多线程连接等功能。 3.1.1 开发背景  随着网络的普及,在网络中交换信息,特别是文件成为使用网络时经常...
  • 很多时候,我们需要把文件传输到服务器上进行运行、部署等操作,在使用windows服务器的时候,我们都会遇到这样的问题:我们应该怎么上传文件到服务器?有没有简单的方法来实现本地文件上传到服务器呢? 很多时候,...
  • 如今,人们处于一个...这就是另外一个需要解决的问题,那就是超大文件传输。 怎样的方式可以解决这些难题呢? 以往我们会上传到某网盘,然后让对方下载。如今看来,这是一类蛮老套的方法了,现在可以和它说拜拜了...
  • Windows系统在安装虚拟机centos系统之后,如何进行两者之间的文件传输和互操作,或者如何在Windows端使用Xshell对Linux端进行远程操作?使用centos的文件上传下载小工具,可以快速的帮助我们从本地上传文件至Linux...
  • 那么,异地大文件传输如何更好的得到实现?有没有好的方法解决大文件远程传输问题呢? 一般我们认为大文件远程传输的关键点在于看双方的上网方式。如果双方都是用同一个ISP的话,可以考虑用QQ传送。举个例子,...
  • Docker容器和本机之间的文件传输

    万次阅读 多人点赞 2017-11-25 20:00:44
    有了这个长长的ID的话,本机和容器之间的文件传输就简单了。docker cp 本地文件路径 ID全称:容器路径进入容器之后就能够看到刚才上传进来的文件了。如果是容器传输文件到本地的话,反过来就好了:docker cp ID全称:...
  • 利用FTP和云服务器进行文件传输首先需要 云服务器配置好FTP环境后,您可以通过: 1.资源管理器 2.第三方软件 与服务器进行文件传输 与服务器进行文件传输时首先要确保服务器安全组开放了21端口(入站规则为TCP21...
  • C# 简单通信(实现文件传输

    千次阅读 2018-08-29 16:43:46
    之前写过一个简单通信传输,不过只有聊天的功能,现在实现了文件传输的功能,借鉴于网上一篇博客,不过他写的仅仅是客户端对于服务器发送文件,我稍微优化了这个功能,实现了,端与端之间信息的互发和文件的互发,...
1 2 3 4 5 ... 20
收藏数 1,514,752
精华内容 605,900
关键字:

文件传输