文件传输思路
Server.cpp
#include <QCoreApplication>
#include <winsock.h>
#include <windows.h> //注意顺序 #include <winsock.h> #include <windows.h>
#include <iostream>
#include <QDebug>
using namespace std;
#pragma comment(lib, "ws2_32.lib")
DWORD WINAPI ThreadFun(LPVOID lpThreadParameter);
#pragma comment(lib, "ws2_32.lib")
struct FileHeader{
char m_szFileName[MAX_PATH];
long m_FileSize;
};
#define MAX_RESULT 5
#define MAX_PAGE 4096
char g_szResult[MAX_RESULT];
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//1.加载库
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
printf("WSAStartup failed with error: %d\n", err);
return 1;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
printf("Could not find a usable version of Winsock.dll\n");
WSACleanup();
return 1;
}
else
printf("The ServerWinsock 2.2 dll was found okay\n");
//2.创建socket
SOCKET sock = socket(AF_INET,SOCK_STREAM,0);
if (sock == INVALID_SOCKET)
{
WSACleanup();
return 1;
}
//3.绑定
sockaddr_in addrserver;
addrserver.sin_family = AF_INET;
addrserver.sin_port = htons(8899);
addrserver.sin_addr.S_un.S_addr=0;
if (SOCKET_ERROR == bind(sock,(const sockaddr*)&addrserver,sizeof(addrserver)))
{
closesocket(sock);
WSACleanup();
return 1;
}
//4.监听事件
//listen只是把套接字从主动变为被动,并限制链接数
if (SOCKET_ERROR == listen(sock,10))//10:服务器进程不能随便指定一个数值,内核有许可的范围
{
closesocket(sock);
WSACleanup();
return 1;
}
//5.拉着客人进店 ,将客人交给服务员
while(1){
SOCKET sockWaiter = accept(sock,0,0);//第一个参数指定处于监听状态的流套接字 第二个参数来返回新创建的套接字的地址结构 第三个参数来返回新创建套接字的地址结构的长度。
CreateThread(0,0, &ThreadFun,(LPVOID)sockWaiter,0,0);
}
//8.下班--closesocket();
closesocket(sock);
//9.关店--WSACleanup();
WSACleanup();
return a.exec();
}
DWORD WINAPI ThreadFun(LPVOID lpThreadParameter)
{
SOCKET sockWaiter = (SOCKET)lpThreadParameter;
FileHeader fh;
int nRecvNum;
//6.接收消息 -- recv();
/*
* s<r normal;
* s>r 分次接
*/
while(1)
{
//文件传输
//1.接收文件信息
nRecvNum = recv(sockWaiter,(char*)&fh,sizeof(FileHeader),0);
if (nRecvNum<=0) continue;
cout<<"filename:"<<fh.m_szFileName<<"file size:"<<fh.m_FileSize<<endl;
qDebug()<<"请输入是否接收文件 yes or no";
cin>>g_szResult;
//2.发送回复 yes no
send(sockWaiter,g_szResult,MAX_RESULT,0);
//3.如果是yes 接收文件
char szpath[MAX_PATH] = {0};
char szContent[MAX_PAGE]={0};
long lfilesize = fh.m_FileSize;
if (0==strcmp(g_szResult,"yes")){
qDebug()<<"请输入要保存的文件路径";
cin>>szpath;
strcat(szpath,fh.m_szFileName);
FILE *pfile = fopen(szpath,"wb");
if (!pfile) continue;
while(lfilesize){
nRecvNum = recv(sockWaiter,szContent,MAX_PAGE,0);
if (nRecvNum > 0)
{
//4.接收文件内容 并写入
fwrite(szContent,sizeof(char),nRecvNum,pfile);
lfilesize -= nRecvNum;
}
}
fclose(pfile);
}
}
return 0;
}
Client.cpp
#include <QCoreApplication>
#include <winsock.h>
#include <iostream>
#include <QDebug>
using namespace std;
#pragma comment(lib, "ws2_32.lib")
struct FileHeader{
char m_szFileName[MAX_PATH];
long m_FileSize;
};
#define MAX_RESULT 5
#define MAX_PAGE 4096
char g_szResult[MAX_RESULT];
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//加载库
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
printf("WSAStartup failed with error: %d\n", err);
return 1;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
printf("Could not find a usable version of Winsock.dll\n");
WSACleanup();
return 1;
}
else
printf("The ClientWinsock 2.2 dll was found okay\n");
//创建socket
SOCKET sock = socket(AF_INET,SOCK_STREAM,0);
if (sock == INVALID_SOCKET)
{
WSACleanup();
return 1;
}
//链接
sockaddr_in addrserver;
addrserver.sin_family = AF_INET;
addrserver.sin_port = htons(8899);
addrserver.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
if (SOCKET_ERROR == connect(sock,(const sockaddr*)&addrserver,sizeof (addrserver)))
{
closesocket(sock);
WSACleanup();
return 1;
}
//文件传输
//1.获取文件名、文件大小
char SZ_FileName[MAX_PATH] = {0};//SZ_FileName:文件路径 MAX_PATH:260字节
qDebug()<<"请输入要传输的文件名";
cin>>SZ_FileName;
char *ptemp = SZ_FileName; //获取文件名:先让指针走到尾部,在往回走
while(*ptemp != '\0') ptemp++;
while(*ptemp != '\\') ptemp--;//“//”代表“/” “/”代表转义字符
ptemp++; //文件名
//文件大小
FILE *pfile = fopen(SZ_FileName,"rb");//rb:以二进制流的方式在读
if(!pfile) return 1;
//fseek():移动文件指针到文件尾:C中没有获取文件大小的方法,但是可以先移动到尾部,在获取当前指针的位置来得到文件的大小
fseek(pfile,0,SEEK_END);
long lFileSize = ftell(pfile);//ftell():获取文件指针指针当前所在位置。
//移动文件指针到文件头
fseek(pfile,0,SEEK_SET);
//2.发送
FileHeader fh;
//结构体成员赋初值
fh.m_FileSize = lFileSize;
strcpy(fh.m_szFileName,ptemp);
send(sock,(const char *)&fh,sizeof(fh),0);
//3.等对方回复 no yes
recv(sock,g_szResult,sizeof(g_szResult),0);
char szContent[MAX_PAGE] = {0};
//4.如果接收的话
if (0 == strcmp(g_szResult,"yes"))
{
while (1)
{
//5.读文件内容
size_t nReadNum = fread(szContent,sizeof(char),MAX_PAGE,pfile);
if (nReadNum > 0)
{
//6.发送
send(sock,szContent,nReadNum,0);
}
else{
break;
}
}
}
//7.关闭文件
fclose(pfile);
//关闭socket
closesocket(sock);
//卸载库
WSACleanup();
return a.exec();
}