对于文件的读写不太熟悉,犯了很多错误。服务器
好比,对于传送的文件中有各类文件,刚开始时用的r打开,只能实现txt文件的传输,而且传输后获得的文件的格式与源文件不一致。还有对于fgets与fread不太了解。并发
fget:tcp
函数原型:char *fgets(char *string, int n, FILE *fp);ide
头文件:#include<stdio.h>函数
是不是标准函数:是测试
函数功能:从fp所指的文件中读取一个长度为(n-1)的字符串,并将该字符串存入以string为起始地址的缓冲区中。fgets函数有三个参数,其中string为缓冲区首地址,n规定了要读取的最大长度,fp为文件指针。ui
返回值:返回地址string,若遇到文件结束符或出错,返回NULL。用feof 或ferror判断是否出错。spa
fread:指针
函数原型:int fread(void *buf, int size, int count, FILE *fp);调试
头文件:#include<stdio.h>
是不是标准函数:是
函数功能:从fp指向的文件中读取长度为size 的count个数据项,并将它输入到以buf为首地址的缓冲区中。此时,文件指针fp会自动增长实际读入数据的字节数,即fp指向最后读入字符的下一个字符位置。
返回值:返回实际读入数据项的个数,即count值。若遇到错误或文件结束返回0。
fwrite:
函数原型:int fwrite(void *buf, int size, int count, FILE *fp);
头文件:#include<stdio.h>
是不是标准函数:是
函数功能:将buf所指向的count*size个字节的数据输出到文件指针fp所指向的文件中去。该函数与fread相对,输出数据后,文件指针fp自动指向输出的最后一个字符的下一个位置。该函数经常使用于分批将数据块输出到文件中。
返回值:返回实际写入文件数据项个数。
在个人使用过程当中感觉是对获取的字符串处理则用fgets,连续读取文件则使用fread。
#include "sock_class.h" #define RESPONSE_BUF_SIZE 4096 #define DATA_BUF_SIZE 4096 int FtpPut(const char* szIP, const char* szPath, const char* szFile); int main(int argc, char *argv[]) { char szData[4096]; if (argc < 4) { printf("USAGE: %s IP Path File", argv[0]); return 1; } if (WinSockInit() != 0) { printf("WSAStartup failed with error \n"); return 1; } int nRet = FtpPut(argv[1], argv[2], argv[3]); WSACleanup(); return nRet; } //处理响应信息 int GetFtpReponse(tcp_sock& sockCtrl, char* szRespBuf, int nLen) { int nRetCode; if (sockCtrl.read_line(szRespBuf, nLen) == SOCKET_ERROR) { printf("GetFtpReponse error!\n"); return 0; } printf(szRespBuf); if (sscanf(szRespBuf, "%ld", &nRetCode) != 1) { printf("GetFtpReponse error(%s)!\n", szRespBuf); return 0; } if (szRespBuf[3] == '-') { do { if (sockCtrl.read_line(szRespBuf, nLen) == SOCKET_ERROR) { printf("GetFtpReponse error!\n"); return 0; } if ((szRespBuf[0] >= '0') && (szRespBuf[0] <= '9')) { break; } } while (1); } return nRetCode; } //发控制信息 int SendFtpCmd(tcp_sock& sockCtrl, const char* szCmd) { if (sockCtrl.write_line(szCmd, strlen(szCmd)) == SOCKET_ERROR) { printf("SendFtpCmd error(%s)!\n", szCmd); return 0; } return 1; } //链接Ftp服务器 int ConnectFtp(tcp_sock& sockCtrl, const char* szIP) { char szRespBuf[RESPONSE_BUF_SIZE + 1]; if (!sockCtrl.connect(szIP, "21")) { printf("connect error!\n"); return 1; } if (GetFtpReponse(sockCtrl, szRespBuf, RESPONSE_BUF_SIZE) != 220) { printf("GetFtpReponse 220 error!\n"); return 1; } return 0; } //登录Ftp服务器 int LoginFtp(tcp_sock& sockCtrl) { char szRespBuf[RESPONSE_BUF_SIZE + 1]; //User Name if (!SendFtpCmd(sockCtrl, "USER Anonymous")) { printf("SendFtpCmd error!\n"); return 1; } if (GetFtpReponse(sockCtrl, szRespBuf, RESPONSE_BUF_SIZE) != 331) { printf("GetFtpReponse 331 error!\n"); return 1; } //Pass if (!SendFtpCmd(sockCtrl, "PASS asdfa@sina.com")) { printf("SendFtpCmd error!\n"); return 1; } if (GetFtpReponse(sockCtrl, szRespBuf, RESPONSE_BUF_SIZE) != 230) { printf("GetFtpReponse 230 error!\n"); return 1; } return 0; } //上传文件 int UpLoadFile(tcp_sock& sockCtrl, const char* szPath, const char* szFile) { tcp_sock sockData; char szRespBuf[RESPONSE_BUF_SIZE + 1]; //切换到根目录 if (!SendFtpCmd(sockCtrl, "CWD /")) { printf("SendFtpCmd CWD error!\n"); return 1; } if (GetFtpReponse(sockCtrl, szRespBuf, RESPONSE_BUF_SIZE) != 250) { printf("GetFtpReponse 250 error!\n"); return 1; } //调试,显示当前目录 if (!SendFtpCmd(sockCtrl, "PWD")) { printf("SendFtpCmd PWD error!\n"); return 1; } if (GetFtpReponse(sockCtrl, szRespBuf, RESPONSE_BUF_SIZE) != 257) { printf("GetFtpReponse 257 error!\n"); return 1; } //设置传送类型为I if (!SendFtpCmd(sockCtrl, "TYPE I")) { printf("SendFtpCmd \"TYPE I\" error!\n"); return 1; } if (GetFtpReponse(sockCtrl, szRespBuf, RESPONSE_BUF_SIZE) != 200) { printf("GetFtpReponse 200 error!\n"); return 1; } //PASV if (!SendFtpCmd(sockCtrl, "PASV")) { printf("SendFtpCmd error!\n"); return 1; } if (GetFtpReponse(sockCtrl, szRespBuf, RESPONSE_BUF_SIZE) != 227) { printf("GetFtpReponse 227 error!\n"); return 1; } char* pPos = strchr(szRespBuf, '('); if (pPos == NULL) { printf("GetFtpReponse Pasv error!\n"); return 1; } int ip1, ip2, ip3, ip4, port1, port2; if (sscanf(pPos, "(%d,%d,%d,%d,%d,%d)", &ip1, &ip2, &ip3, &ip4, &port1, &port2) != 6) { printf("GetFtpReponse Pasv Address error!\n"); return 1; } //生成ip与端口 char szIP[50]; char szPort[10]; sprintf(szIP, "%d.%d.%d.%d", ip1, ip2, ip3, ip4); sprintf(szPort, "%d", port1*256 + port2); //数据链接 if (!sockData.connect(szIP, szPort)) { printf("Data connect error!\n"); return 1; } //STOR char szCmdSTOR[100]; sprintf(szCmdSTOR, "STOR %s", szFile); if (!SendFtpCmd(sockCtrl, szCmdSTOR))//发送文件的命令 { printf("SendFtpCmd \"STOR %s\" error!\n",szFile); return 1; } if (GetFtpReponse(sockCtrl, szRespBuf, RESPONSE_BUF_SIZE) != 150) { printf("GetFtpReponse 150 error!\n"); return 1; } //把文件读入缓冲区 FILE* fp = fopen(szFile, "rb");//必须是rb:二进制打开,只读 if(fp == NULL) { printf("Open file %s Error! \n", szFile); return 1; } char szBuf[DATA_BUF_SIZE]; int nReaded = 0; while(1) { nReaded = fread(szBuf,sizeof(char), DATA_BUF_SIZE, fp);//读入到szBuf,最多读入DATA_BUF_SIZE*sizeof(char) //printf("--nReaded:%d\n",nReaded);//测试 if (nReaded == 0) break; //szBuf中数据写入套接字缓冲区并发送 sockData.write(szBuf, nReaded); memcpy(szBuf,"\0",DATA_BUF_SIZE); //printf("sended\n\n");//测试 } //printf("out\n");//测试 sockData.close(); fclose(fp); //接收成功吗? if (GetFtpReponse(sockCtrl, szRespBuf, RESPONSE_BUF_SIZE) != 226) { printf("GetFtpReponse 226 error!\n"); return 1; } return 0; } //退出登陆 int LogoutFtp(tcp_sock& sockCtrl) { char szRespBuf[RESPONSE_BUF_SIZE + 1]; //QUIT if (!SendFtpCmd(sockCtrl, "QUIT")) { printf("SendFtpCmd Quit error!\n"); return 1; } if (GetFtpReponse(sockCtrl, szRespBuf, RESPONSE_BUF_SIZE) != 221) { printf("GetFtpReponse 221 error!\n"); return 1; } return 0; } //向ftp服务器发送文件 int FtpPut(const char* szIP, const char* szPath, const char* szFile) { tcp_sock sockCtrl; char szRespBuf[RESPONSE_BUF_SIZE + 1]; if (ConnectFtp(sockCtrl, szIP) != 0) return 1; if (LoginFtp(sockCtrl) != 0) return 1; if (UpLoadFile(sockCtrl, szPath, szFile) != 0) return 1; LogoutFtp(sockCtrl); return 0; }