小鱼儿----文件传送工具(支持打同时接收和传送)c语言版 0.1
这个版本用的几乎都是用c 能不用API 就不API。。可以同时支持接收文件和传送文件。
但不支持断点传送。自己还没有学。。
传送的时候没有显示。在文件传送完会提示的。。
程序代码:
头文件: #ifndef FILE_SEND_TOOL_H #define FILE_SEND_TOOL_H #include <WINDOWS.H> #include <stdio.h> #include <WINSOCK.H> #include <IO.H> #pragma comment(lib,"ws2_32") #define CHUNK_SIZE (1024*64) #define BUF_LEN 1024 #define BIND_PORT 6665 //本身绑定端口 #define RECV_PORT 6667 //接受端口 #define CHEKPASS 0 //验证密码 这个不想在c的控制台实现。 #define RECVFile 1 //接受文件 #define SURE_GETFILE 3 //接受文件做好准备 typedef struct tagFileInfo { int FileSize; char FileName[MAX_PATH]; BOOL IsFolder; }FileInfo; typedef struct tagCOMMENT { int ID; char lparam[BUF_LEN]; }COMMENT; SOCKET Server; SOCKET Client; SOCKADDR_IN ServerAddr; int SureGetFile = 0; //可以发送文件信号 char Pass[12]; //保存连接的时候密码 //char SaveName[MAX_PATH]; //接收文件的时候保存的文件名 DWORD WINAPI SendProc(LPVOID lparam); //发送文件线程 DWORD WINAPI RunProc(LPVOID lparam); void RecvFile(char *buf,SOCKET Client1); void SendFile(char *filename,char *ip); void UserMenu(); //保存用户信息用于保存在硬盘上 //用于以后扩展的结构 typedef struct tagUSER { char IP[32+1]; char UserName[MAX_PATH]; }USER; #endif下面是cpp
程序代码:
#include "FileSendTool.h" int main() { WSADATA wsa; WSAStartup(MAKEWORD(2,2),&wsa); Server = socket(AF_INET,SOCK_STREAM,0); if(Server == INVALID_SOCKET) { puts("创建套接字失败"); return 0; } ServerAddr.sin_addr.S_un.S_addr =htonl(INADDR_ANY); ServerAddr.sin_family = AF_INET; ServerAddr.sin_port = htons(BIND_PORT); if(bind(Server,(SOCKADDR*)&ServerAddr,sizeof(ServerAddr)) == SOCKET_ERROR) { puts("端口绑定失败"); return 0; } if(listen(Server,5) == SOCKET_ERROR) { puts("listen 失败"); return 0; } char buf[BUF_LEN]; memset(buf,0,sizeof(buf)); CreateThread(0,0,SendProc,0,0,0); while(1) { int len = sizeof(ServerAddr); Client = accept(Server,(SOCKADDR*)&ServerAddr,&len); if(Client == INVALID_SOCKET) { continue; } CreateThread(0,0,RunProc,(LPVOID)Client,0,0); } } DWORD WINAPI RunProc(LPVOID lparam) { int flag = 1; SOCKET Client = (SOCKET)lparam; while(flag) { COMMENT cmd; memset(&cmd,0,sizeof(cmd)); int ret = recv(Client,(char*)&cmd,sizeof(cmd),0); if(SOCKET_ERROR == ret) { puts("网络出现错误"); } switch(cmd.ID) { case CHEKPASS: break; case RECVFile: RecvFile(cmd.lparam,Client); flag = 0; break; default: break; } } return 0; } void RecvFile(char *buf,SOCKET Client1) { FileInfo fi; int nLeft = 0; int nRead = 0; char date[CHUNK_SIZE]; memset(date,0,sizeof(date)); SOCKET Rfs; SOCKADDR_IN addr; Rfs = socket(AF_INET,SOCK_STREAM,0); addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); addr.sin_family = AF_INET; addr.sin_port = htons(RECV_PORT); if(bind(Rfs,(SOCKADDR*)&addr,sizeof(addr))==SOCKET_ERROR) { puts("绑定文件接受端口失败"); closesocket(Rfs); return; } if(listen(Rfs,5) == SOCKET_ERROR) { puts("listen 接受文件失败"); closesocket(Rfs); return; } COMMENT cmd; cmd.ID = SURE_GETFILE; if(send(Client1,(char*)&cmd,sizeof(cmd),0) == SOCKET_ERROR) //发送确定接受文件消息 { puts("对方已经退出"); closesocket(Rfs); return; } int len = sizeof(addr); SOCKET Client = accept(Rfs,(SOCKADDR*)&addr,&len); if(Client == INVALID_SOCKET) { puts("accept 接受文件失败"); closesocket(Client); closesocket(Rfs); return; } memcpy(&fi,buf,sizeof(FileInfo)); int nCount = fi.FileSize/CHUNK_SIZE; if(nCount == 0 || nCount*CHUNK_SIZE!=fi.FileSize) { nCount++; } char name[MAX_PATH]; memset(name,0,sizeof(name)); strcpy(name,strrchr(fi.FileName,'\\')+1); //获取文件名而不是full name 保存在当前目录 因为 //我这个程序设计几个线程 别的线程也有关于控制台的读写 我就不好要用户写入要保存的位置。 //puts("文件名字"); //puts(name); FILE *fw = fopen(name,"wb"); for(int i =0; i<nCount; i++) { if(i+1 == nCount) { nLeft = fi.FileSize - (nCount-1)*CHUNK_SIZE; } else { nLeft = CHUNK_SIZE; } while(nLeft>0) { int ret = recv(Client,&date[nRead],nLeft,0); if(ret == SOCKET_ERROR ||ret ==0) { puts("网络出现问题"); closesocket(Client); closesocket(Rfs); return; } //printf("接受数据%d\n",ret); nRead+=ret; nLeft-=ret; } fwrite(date,sizeof(char),CHUNK_SIZE,fw); nRead = 0; } fclose(fw); closesocket(Rfs); closesocket(Client); //puts("接受完成"); MessageBox(0,"接受完成",0,0); } void SendFile(char *filename,char *ip) { SOCKET SendS; SOCKADDR_IN SerVerAddr; SerVerAddr.sin_addr.S_un.S_addr = inet_addr(ip); SerVerAddr.sin_family = AF_INET; SerVerAddr.sin_port = htons(RECV_PORT); SendS = socket(AF_INET,SOCK_STREAM,0); if(INVALID_SOCKET == SendS) { puts("创建传送套接字失败"); return; } if(connect(SendS,(SOCKADDR*)&SerVerAddr,sizeof(SerVerAddr)) == SOCKET_ERROR) { puts("连接错误"); closesocket(SendS); } //puts("接入文件传送端口"); FileInfo fi; int nRead = 0; int nLeft = 0; char date[CHUNK_SIZE]; memset(date,0,sizeof(date)); strcpy(fi.FileName,filename); FILE *fp = fopen(fi.FileName,"rb"); if(NULL == fp) { puts("打开文件失败"); closesocket(SendS); return; } fseek(fp,0,SEEK_END); fi.FileSize = ftell(fp); rewind(fp); //printf("文件大小 %d",fi.FileSize); int nCount = fi.FileSize/CHUNK_SIZE; if(nCount == 0 || nCount*CHUNK_SIZE != fi.FileSize) { nCount++; } //printf("nCount is %d\n",nCount); for(int i =0; i < nCount ; i++) { if(i+1 ==nCount) { nLeft = fi.FileSize - (nCount-1)*CHUNK_SIZE; } else { nLeft = CHUNK_SIZE; } fread(date,sizeof(char),nLeft,fp); while(nLeft >0) { int ret = send(SendS,&date[nRead],nLeft,0); //printf("lk %d",GetLastError()); if(SOCKET_ERROR == ret) { puts("文件传送出现错误"); closesocket(SendS); int len = GetLastError(); printf("错误代码 %d",len); return; } Sleep(10); //printf("传送数据 %d",nRead); nRead+=ret; nLeft-=ret; } nRead =0; } //puts("传送完成"); //Sleep(10); MessageBox(0,"传送完成",0,0); fclose(fp); closesocket(SendS); } void UserMenu() { char ip[32+1]; char filename[MAX_PATH]; memset(ip,0,sizeof(ip)); memset(filename,0,sizeof(filename)); FILE *fp; while(1) { system("cls"); puts("\t\t 欢迎使用小鱼儿文件传送工具"); puts("\t你需要传送数据吗:(1 是 0 否 2代表推出程序)"); int ret = -1; scanf("%d",&ret); fflush(stdin); switch(ret) { case 1: puts("请输入对方的IP地址"); gets(ip); fflush(stdin); puts("请输入文件名字"); gets(filename); fflush(stdin); if(strlen(ip) == 0||strlen(filename) == 0) { puts("请输入正确的数据"); continue; } SOCKET Client; SOCKADDR_IN Addr; Client = socket(AF_INET,SOCK_STREAM,0); //创建套接字与对方创建发送文件 if(Client == INVALID_SOCKET) { puts("UserMenu 创建套接字失败"); exit(3); return; } Addr.sin_addr.S_un.S_addr = inet_addr(ip); Addr.sin_family = AF_INET; Addr.sin_port = htons(BIND_PORT); COMMENT cmd; cmd.ID = RECVFile; FileInfo fi; strcpy(fi.FileName,filename); fp = fopen(filename,"rb"); if(NULL == fp) { puts("打开文件失败"); closesocket(Client); continue; } //获得文件大小 fseek(fp,0,SEEK_END); fi.FileSize = ftell(fp); fclose(fp); if(connect(Client,(SOCKADDR*)&Addr,sizeof(Addr))== SOCKET_ERROR) { puts("连接出现错误"); closesocket(Client); continue; } memcpy(cmd.lparam,&fi,sizeof(fi)); //发送要传送文件信息 if(send(Client,(char*)&cmd,sizeof(cmd),0) == SOCKET_ERROR) { puts("发送文件失败"); closesocket(Client); continue; } memset(&cmd,0,sizeof(cmd)); //等被接收放发送信息来确认 if(recv(Client,(char*)&cmd,sizeof(cmd),0) == SOCKET_ERROR) { puts("接受文件失败"); closesocket(Client); continue; } SendFile(filename,ip); break; case 2: closesocket(Server); WSACleanup(); exit(3); break; default: system("cls"); break; } } } DWORD WINAPI SendProc(LPVOID lparam) { while(1) { UserMenu(); } }
附件:
小鱼儿文件传送工具.zip
(24.54 KB)
[ 本帖最后由 小鱼儿c 于 2012-3-7 21:56 编辑 ]