1. 程式人生 > >使用C語言socket實現windows pc與ftp伺服器通訊---socket實現ftp客戶端

使用C語言socket實現windows pc與ftp伺服器通訊---socket實現ftp客戶端

code

// Client.cpp : 定義控制檯應用程式的入口點。
//

#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <WinSock2.h>
#pragma comment(lib,"WS2_32.lib")
using namespace std;

#define PORT 21		//FTP埠
#define IP_ADDR "x.x.x.x"	//主機地址

int getPortNum(char* buf);
bool executeFTPCmd(SOCKET controlSocket, char* buf, int len, int stateCode);
int getStateCode(char* buf);

int main()
{
	WSADATA dat;
	SOCKET controlSocket, dataSocket;
	SOCKADDR_IN serverAddr;
	int dataPort, ret, stateCode;
	char buf[100]={0}, sendBuf[1024]={0};
	
	//初始化,很重要
	if (WSAStartup(MAKEWORD(2,2),&dat)!=0)	//Windows Sockets Asynchronous啟動
	{
		cout<<"Init Falied: "<<GetLastError()<<endl;
		system("pause");
		return -1;
	}

	//建立Socket
	controlSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	if(controlSocket==INVALID_SOCKET)
	{
		cout<<"Creating Control Socket Failed: "<<GetLastError()<<endl;
		system("pause");
		return -1;
	}
	//構建伺服器訪問引數結構體
	serverAddr.sin_family=AF_INET;
	serverAddr.sin_addr.S_un.S_addr=inet_addr(IP_ADDR);	//地址
	serverAddr.sin_port=htons(PORT);			//埠
	memset(serverAddr.sin_zero,0,sizeof(serverAddr.sin_zero));
	//連線
	ret=connect(controlSocket,(struct sockaddr*)&serverAddr,sizeof(serverAddr));
	if(ret==SOCKET_ERROR)
	{
		cout<<"Control Socket connecting Failed: "<<GetLastError()<<endl;
		system("pause");
		return -1;
	}
	cout<<"Control Socket connecting is success."<<endl;
	//接收返回狀態資訊
	recv(controlSocket,buf,100,0);
	cout<<buf;													//220
	//根據返回資訊提取狀態碼,進行判斷
	if(getStateCode(buf) != 220)
	{
		cout<<"Error: Control Socket connecting Failed"<<endl;
		system("pause");
		exit(-1);
	}
	//使用者名稱
	memset(buf,0,100);
	sprintf(buf,"USER %s\r\n","xxxx");
	executeFTPCmd(controlSocket, buf, 100, 331);				//331
	//密碼
	memset(buf,0,100);
	sprintf(buf,"PASS %s\r\n","xxxx");
	executeFTPCmd(controlSocket, buf, 100, 230);			//230
	//=======================================
	//切換到被動模式
	memset(buf,0,100);
	sprintf(buf,"PASV\r\n");
	executeFTPCmd(controlSocket, buf, 100, 227);				//227
	//返回的資訊格式為---h1,h2,h3,h4,p1,p2
	//其中h1,h2,h3,h4為伺服器的地址,p1*256+p2為資料埠
	dataPort=getPortNum(buf);
	//客戶端資料傳輸socket
	dataSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	serverAddr.sin_port=htons(dataPort);	//更改連線引數中的port值
	ret=connect(dataSocket,(struct sockaddr*)&serverAddr,sizeof(serverAddr));
	if(ret==SOCKET_ERROR)
	{
		cout<<"Data Socket connecting Failed: "<<GetLastError()<<endl;
		system("pause");
		return -1;
	}
	cout<<"Data Socket connecting is success."<<endl;
	//更改當前目錄
	memset(buf,0,100);
	sprintf(buf,"CWD %s\r\n","/ftpxxxx/web/monitor");	//250
	executeFTPCmd(controlSocket, buf, 100, 250);
	//上傳檔案
	memset(buf,0,100);
	sprintf(buf,"STOR %s\r\n","1.jpg");
	executeFTPCmd(controlSocket, buf, 100, 125);						//125

	FILE* f=fopen("1.jpg","rb");
	if(f==NULL)
	{
		cout<<"The file pointer is NULL!"<<endl;
		cout<<"Error: "<<__FILE__<<" "<<__LINE__<<endl;
		exit(-1);
	}
	while( !feof(f) )
	{
		fread(sendBuf, 1, 1024, f);
		send(dataSocket, sendBuf, 1024, 0);
	}
	fclose(f);
	
	//釋放資源
	closesocket(dataSocket);
	closesocket(controlSocket);
	WSACleanup();
	system("pause");
	return 0;
}

//從返回資訊“227 Entering Passive Mode (182,18,8,37,10,25).”中
//獲取資料埠
int getPortNum(char* buf)
{
	int num1=0,num2=0;

	char* p=buf;
	int cnt=0;
	while( 1 )
	{
		if(cnt == 4 && (*p) != ',')
		{
			num1 = 10*num1+(*p)-'0';
		}
		if(cnt == 5)
		{
			num2 = 10*num2+(*p)-'0';
		}
		if((*p) == ',')
		{
			cnt++;
		}
		p++;
		if((*p) == ')')
		{
			break;
		}
	}
	cout<<"The data port number is "<<num1*256+num2<<endl;
	return num1*256+num2;
}
//通過控制socket執行FTP命令
bool executeFTPCmd(SOCKET controlSocket, char* buf, int len, int stateCode)
{
	send(controlSocket, buf, len, 0);
	memset(buf, 0, len);
	recv(controlSocket, buf, 100, 0);
	cout<<buf;
	if(getStateCode(buf) == stateCode)
	{
		return true;
	}
	else
	{
		cout<<"The StateCode is Error!"<<endl;
		return false;
	}
}
//從返回資訊中獲取狀態碼
int getStateCode(char* buf)
{
	int num=0;
	char* p=buf;
	while(p != NULL)
	{
		num=10*num+(*p)-'0';
		p++;
		if(*p==' ')
		{
			break;
		}
	}

	return num;
}