/* * WinSock实现网络文件传输程序 * Windows 2003 + Visual C++ 6.0 编译通过 * brick 2007.4.1 */ /////////////////////////////////////////////////////////////////////////////// #pragma comment(lib, "ws2_32.lib") #i nclude<stdio.h> #i nclude<string.h> #i nclude<winsock2.h> #i nclude<windows.h> #i nclude<assert.h>
#define CHARLENGTH 80 //字符串长// #define SEND_BUFFER_SIZE 1024 //发送缓冲区// #define RECV_BUFFER_SIZE 1024 //接收缓冲区// #define PORT 8508 //默认端口// #define TRUE 1 #define FALSE 0
enum {CMD_NAME};
int RecvFile(); //接收 int SendFile(); //发送 int usage(char msg[]); //帮助提示
int main(int argc, char *argv[]) {
char operate[CHARLENGTH]; memset(operate, '\0', sizeof(operate)); usage(argv[CMD_NAME]);
while (printf("\n\n") && printf("请输入参数 : ") && scanf("\n%s", operate) != EOF) { if (strlen(operate) > 2 ) { usage(argv[CMD_NAME]); continue; } switch (operate[1]) { case 'r': RecvFile(); break; case 's': SendFile(); break; case 'q': printf("谢谢使用 [%s]\nByeBye!\n\n", argv[CMD_NAME]); return(0); break; default : usage(argv[CMD_NAME]); break; } }
return(0); }
/////////////////////////////////////////////////////////////////////////////// //接收函数 int RecvFile() {
char filePath[CHARLENGTH];
printf("请输入保存文件的绝对路径 :\n"); //获取文件保存路径// memset(&filePath, '\0', sizeof(filePath)); scanf("\n%s", filePath);
WSADATA wsaData; WSAStartup(WINSOCK_VERSION, &wsaData);
//建立连接// /////////////////////////////////////////////////////////////////////////// SOCKET sockrecv = socket(AF_INET, SOCK_STREAM, 0); //创建套接字//
if (sockrecv < 0) { closesocket(sockrecv); WSACleanup(); perror("sock"); printf("警告: 创建套接字失败!\n"); return(FALSE); } SOCKADDR_IN addrSrv; memset(&addrSrv, '\0', sizeof(addrSrv)); addrSrv.sin_family = AF_INET; addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //填充本地ip// addrSrv.sin_port = htons(PORT); //填充默认端口//
int ret1 = bind(sockrecv, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR)); //绑定套接字// if (ret1 < 0) { closesocket(sockrecv); WSACleanup(); perror("bind"); printf("警告: 绑定失败!\n"); return(FALSE); }
printf("等待连接......"); int ret2 = listen(sockrecv, 5); //开始监听,限制5个连接// if (ret2 < 0) { closesocket(sockrecv); WSACleanup(); perror("listen"); printf("警告: 监听失败!\n"); return(FALSE); }
SOCKADDR_IN addrCli; memset(&addrCli, '\0', sizeof(addrCli)); int len = sizeof(SOCKADDR); SOCKET sockCli=accept(sockrecv, (SOCKADDR*)&addrCli, &len); //开始接收// if(sockCli < 0) { closesocket(sockrecv); WSACleanup(); perror("accept"); printf("警告: 接收失败!\n"); return(FALSE); }
printf("已经连接 %s\n", inet_ntoa(addrCli.sin_addr)); //显示连接端信息//
int fileLength, cbBytesRet, cbLeftToRecv; BYTE* recvData = NULL;
//创建文件// HANDLE hFile; hFile = CreateFile( filePath, //string 文件名或者绝对路径 GENERIC_WRITE, //long 读写权限,如果为零,表示只允许获取与一个设备有关的信息 FILE_SHARE_WRITE, //long 零表示不共享,FILE_SHARE_READ 或 FILE_SHARE_WRITE 表示允许对文件进行共享访问 NULL, //指向SECURITY_ATTRIBUTES结构的指针,判定返回的句柄是否可以被子进程继承,定义了文件的安全特性,用null表示不被继承。 OPEN_ALWAYS, //long 创建文件,如文件存在则会出错 0, //long 文件默认属性 NULL); //long 如果不为零,则指定一个文件句柄。新文件将从这个文件中复制扩展属性 assert(hFile && "CreateFile!"); /* FILE* hFile; hFile = fopen(filePath, "wb"); */
printf("正在接收文件......\n"); /////////////////////////////////////////////////////////////////////////// //首先接收文件长度信息// cbLeftToRecv = sizeof(fileLength);
do { BYTE* bp = (BYTE*)(&fileLength) + sizeof(fileLength) - cbLeftToRecv; cbBytesRet = recv(sockCli, (char*)bp, cbLeftToRecv, 0); //流型数据的接收处理//
if (cbBytesRet < 0 || cbBytesRet == 0 ) { perror("recv"); printf("警告: 接收文件长度失败!\n"); goto PreReturn; } cbLeftToRecv -= cbBytesRet; } while (cbLeftToRecv > 0);
fileLength = ntohl(fileLength); //将文件的长度信息转化为本地字节序//
/////////////////////////////////////////////////////////////////////////// //开始接收文件
recvData = new BYTE[RECV_BUFFER_SIZE]; cbLeftToRecv = fileLength;
do { int iiGet, iiRecv; iiGet = (cbLeftToRecv < RECV_BUFFER_SIZE) ? cbLeftToRecv : RECV_BUFFER_SIZE; iiRecv = recv(sockCli, (char*)recvData, iiGet, 0); //流型数据的接收处理//
//printf("cbLeftToRecv %d iiGet %d iiRecv %d sizeof(recvData) %d\n", cbLeftToRecv, iiGet, iiRecv, sizeof(recvData)); if (iiRecv < 0 || iiRecv == 0) { perror("recv"); printf("警告: 接收文件失败!\n"); goto PreReturn; }
DWORD dwLen; int ret3 = WriteFile(hFile, //Long,一个文件的句柄 recvData, //Any,要写入的一个数据缓冲区 iiRecv, //Long,要写入数据的字节数量。如写入零字节,表示什么都不写入,针对位于远程系统的命名管道,限制在65535个字节以内 &dwLen, //Long,实际写入文件的字节数量 NULL); //OVERLAPPED,倘若在指定FILE_FLAG_OVERLAPPED的前提下打开文件,这个参数就必须引用一个特殊的结构。 //那个结构定义了一次异步写操作。否则,该参数应置为空(将声明变为ByVal As Long,并传递零值) /* int ret3 = fwrite(recvData, RECV_BUFFER_SIZE, 1, hFile); if (ret3 == 0) printf("警告: 文件写入出错!\n"); */ cbLeftToRecv -= iiRecv;
} while (cbLeftToRecv > 0); printf("发送完成.\n");
/* fclose(hFile); hFile = fopen(filePath, "rb"); if (hFile !=NULL) { //取得文件大小// fseek(hFile, 0L, SEEK_END); fileLength = ftell(hFile); fseek(hFile, 0L, SEEK_SET); } */ //fileLength = GetFileSize(hFile, NULL); //printf("test: 文件长度 %d\n", fileLength); //接收结束,释放内存,关闭连接// PreReturn : delete recvData; CloseHandle(hFile); closesocket(sockrecv); WSACleanup();
return(0); }
/////////////////////////////////////////////////////////////////////////////// //发送函数 int SendFile() {
char filePath[CHARLENGTH]; char DST_IP[CHARLENGTH]; DWORD dst_ip;
printf("请输入目的IP地址 :\n"); memset(&DST_IP, '\0', sizeof(DST_IP)); scanf("\n%s", DST_IP); printf("请输入待发送文件的绝对地址 :\n"); scanf("\n%s", filePath);
WSADATA wsaData; WSAStartup(WINSOCK_VERSION, &wsaData);
dst_ip = inet_addr(DST_IP); //取得目的ip//
//建立连接// /////////////////////////////////////////////////////////////////////////// SOCKET socksend = socket(AF_INET, SOCK_STREAM, 0); //创建套接字// if (socksend < 0) { closesocket(socksend); WSACleanup(); perror("socket"); printf("警告: 创建套接字失败!\n"); return(FALSE); }
SOCKADDR_IN addrSrv; //struct sockaddr_in// memset(&addrSrv, 0, sizeof(addrSrv)); //初始化addr// addrSrv.sin_family = AF_INET; addrSrv.sin_addr.s_addr = dst_ip; //填充目的ip// addrSrv.sin_port = htons(PORT); //填充默认端口//
int ret1 = connect(socksend, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR_IN)); //连接目的地址// if (ret1 < 0) { closesocket(socksend); WSACleanup(); perror("connect"); printf("警告: 连接失败!\n"); return(FALSE); } int fileLength, cbLeftToSend; BYTE* sendData = NULL;
HANDLE hFile; hFile = CreateFile(filePath, //打开要传送的文件// GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); assert(hFile && "CreateFile failed!"); /* FILE* hFile; hFile = fopen(filePath, "rb"); //打开要传送的文件//
if (hFile !=NULL) { //取得文件大小// fseek(hFile, 0L, SEEK_END); fileLength = ftell(hFile); } */ fileLength = GetFileSize(hFile, NULL); printf("正在发送文件......\n"); /////////////////////////////////////////////////////////////////////////// //首先传送文件长度给接收端// fileLength = htonl(fileLength); //转化为网络字序// cbLeftToSend = sizeof(fileLength);
//printf("fileLength %d cbLeftToSend %d\n", fileLength, cbLeftToSend);
do { int cbBytesSend; BYTE* bp = (BYTE*)(&fileLength) + sizeof(fileLength) - cbLeftToSend; cbBytesSend = send(socksend, (const char*)bp, cbLeftToSend, 0);
if (cbBytesSend < 0) { perror("send"); printf("警告: 传送文件长度错误!\n"); goto PreReturn; }
cbLeftToSend -= cbBytesSend;
} while (cbLeftToSend > 0);
/////////////////////////////////////////////////////////////////////////// //开始发送文件//
sendData = new BYTE[SEND_BUFFER_SIZE]; assert(sendData && "Allocate memory failed!"); cbLeftToSend = GetFileSize(hFile, NULL);
do { //循环发送// int sendThisTime, doneSoFar, buffOffset; DWORD dwLen; sendThisTime = ReadFile(hFile, sendData, SEND_BUFFER_SIZE, &dwLen, NULL); sendThisTime = dwLen; /* memset(sendData, 0, sizeof(sendData)); fread(sendData, SEND_BUFFER_SIZE, 1, hFile); sendThisTime = sizeof(sendData); */
buffOffset = 0;
//printf("cbLeftToSend %d字节 sendThisTime %d dwLen %d\n", cbLeftToSend, sendThisTime, dwLen); do { doneSoFar = send(socksend, (const char*)(sendData + buffOffset), sendThisTime, 0);
//printf("1 cbLeftToSend %d sendThisTime %d buffOffset %d doneSoFar %d\n", cbLeftToSend, sendThisTime, buffOffset, doneSoFar);
if (doneSoFar < 0) { perror("send"); printf("警告: 文件发送错误!\n"); goto PreReturn; }
buffOffset += doneSoFar; sendThisTime -= doneSoFar; cbLeftToSend -= doneSoFar;
//printf("2 cbLeftToSend %d sendThisTime %d buffOffset %d doneSoFar %d\n", cbLeftToSend, sendThisTime, buffOffset, doneSoFar);
} while (sendThisTime > 0); } while (cbLeftToSend > 0);
printf("发送完成.\n");
//发送结束,释放内存,关闭连接// PreReturn : delete sendData; closesocket(socksend); WSACleanup();
return(0); }
int usage(char msg[]) { printf( " -----------------------------------------------------------\n" "| 准备好接收数据请输入 -r |\n" "| 准备好发送数据请输入 -s |\n" "| 获取帮助请输入 -h |\n" "| 退出本程序请输入 -q |\n" " -----------------------------------------------------------\n%s\n", msg); return(TRUE); }
|