使用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】服务器端:
头文件:
[cpp]
/*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文件:
[cpp]
/*Server.cpp*/
#include"Server.h"
char g_szNewFileName[MAXFILEDIRLENGTH];
char g_szBuff[MAX_PACKET_SIZE + 1];
long g_lLength;