對於文件的讀寫不太熟悉,犯了很多錯誤。服務器
好比,對於傳送的文件中有各類文件,剛開始時用的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; }