小鱼儿----文件传送工具(支持打同时接收和传送)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();
}
}附件:
[ 本帖最后由 小鱼儿c 于 2012-3-7 21:56 编辑 ]









