网络编程项目实例(编程项目实例网站)
C语言与网络问题 高手进
ping命令是dos命令可以创建一个cmd进程,然后建立两个管道用来得到结果 实现.
下面是一个网络编程的实例, Syn扫描器代码,可以作为参考.
基本可以看为是 ping命令的实现
//getallIP.cpp
#include winsock2.h
#include stdio.h
#pragma comment(lib,"ws2_32.lib")
int main()
{
////////////////
// 初始化 Windows sockets API.
//
WORD wVersionRequested = MAKEWORD(2, 2);
WSADATA wsaData;
if (WSAStartup(wVersionRequested, wsaData)) {
printf("WSAStartup failed %s\n", WSAGetLastError());
return 0;
}
//////////////////
// 获得主机名.
//
char hostname[256];
int res = gethostname(hostname, sizeof(hostname));
if (res != 0) {
printf("Error: %u\n", WSAGetLastError());
return 0;
}
printf("hostname=%s\n", hostname);
////////////////
// 根据主机名获取主机信息.
//
hostent* pHostent = gethostbyname(hostname);
if (pHostent==NULL) {
printf("Error: %u\n", WSAGetLastError());
return 0;
}
//////////////////
// 解析返回的hostent信息.
//
hostent he = *pHostent;
printf("name=%s\naliases=%s\naddrtype=%d\nlength=%d\n",
he.h_name, he.h_aliases, he.h_addrtype, he.h_length);
sockaddr_in sa;
//根据 he.h_addr_list[nAdapter]是否为空来获取所有IP地址
for (int nAdapter=0; he.h_addr_list[nAdapter]; nAdapter++) {
memcpy ( sa.sin_addr.s_addr, he.h_addr_list[nAdapter],he.h_length);
// 输出机器的IP地址.
printf("Address [%d%]: %s\n",nAdapter, inet_ntoa(sa.sin_addr)); // 显示地址串
}
//////////////////
// 终止 Windows sockets API
//
WSACleanup();
return 0;
}
//mstcpip.h
// Copyright (C) Microsoft Corporation, 1996-1999
#if _MSC_VER 1000
#pragma once
#endif
/* Argument structure for SIO_KEEPALIVE_VALS */
struct tcp_keepalive {
u_long onoff;
u_long keepalivetime;
u_long keepaliveinterval;
};
// New WSAIoctl Options
#define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)
#define SIO_RCVALL_MCAST _WSAIOW(IOC_VENDOR,2)
#define SIO_RCVALL_IGMPMCAST _WSAIOW(IOC_VENDOR,3)
#define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR,4)
#define SIO_ABSORB_RTRALERT _WSAIOW(IOC_VENDOR,5)
#define SIO_UCAST_IF _WSAIOW(IOC_VENDOR,6)
#define SIO_LIMIT_BROADCASTS _WSAIOW(IOC_VENDOR,7)
#define SIO_INDEX_BIND _WSAIOW(IOC_VENDOR,8)
#define SIO_INDEX_MCASTIF _WSAIOW(IOC_VENDOR,9)
#define SIO_INDEX_ADD_MCAST _WSAIOW(IOC_VENDOR,10)
#define SIO_INDEX_DEL_MCAST _WSAIOW(IOC_VENDOR,11)
//synscan.cpp
#include winsock2.h
#include ws2tcpip.h
#include stdio.h
#include time.h
#include "mstcpip.h"
#pragma comment(lib,"ws2_32.lib")
#define SEQ 0x28376839
SOCKET sockRaw = INVALID_SOCKET,
sockListen = INVALID_SOCKET;
struct sockaddr_in dest;
BOOL ScanOK=FALSE;
char *DEST_HOST;
int DEST_PORT;
int DEST_PORTEND;
int play=0;
clock_t start,end;//程序运行的起始和结束时间
float costtime;//程序耗时
typedef struct _iphdr
{
unsigned char h_lenver; //4位首部长度+4位IP版本号
unsigned char tos; //8位服务类型TOS
unsigned short total_len; //16位总长度(字节)
unsigned short ident; //16位标识
unsigned short frag_and_flags; //3位标志位
unsigned char ttl; //8位生存时间 TTL
unsigned char proto; //8位协议 (TCP, UDP 或其他)
unsigned short checksum; //16位IP首部校验和
unsigned int sourceIP; //32位源IP地址
unsigned int destIP; //32位目的IP地址
}IP_HEADER;
typedef struct _tcphdr //定义TCP首部
{
USHORT th_sport; //16位源端口
USHORT th_dport; //16位目的端口
unsigned int th_seq; //32位序列号
unsigned int th_ack; //32位确认号
unsigned char th_lenres; //4位首部长度/6位保留字
unsigned char th_flag; //6位标志位
USHORT th_win; //16位窗口大小
USHORT th_sum; //16位校验和
USHORT th_urp; //16位紧急数据偏移量
}TCP_HEADER;
struct //定义TCP伪首部
{
unsigned long saddr; //源地址
unsigned long daddr; //目的地址
char mbz;
char ptcl; //协议类型
unsigned short tcpl; //TCP长度
}psd_header;
//SOCK错误处理程序
void CheckSockError(int iErrorCode, char *pErrorMsg)
{
if(iErrorCode==SOCKET_ERROR)
{
printf("%s Error:%d\n", pErrorMsg, GetLastError());
closesocket(sockRaw);
ExitProcess(-1);
}
}
//计算检验和
USHORT checksum(USHORT *buffer, int size)
{
unsigned long cksum=0;
while (size 1)
{
cksum += *buffer++;
size -= sizeof(USHORT);
}
if (size)
{
cksum += *(UCHAR*)buffer;
}
cksum = (cksum 16) + (cksum 0xffff);
cksum += (cksum 16);
return (USHORT)(~cksum);
}
//IP解包程序
bool DecodeIPHeader(char *buf, int bytes)
{
IP_HEADER *iphdr;
TCP_HEADER *tcphdr;
unsigned short iphdrlen;
iphdr = (IP_HEADER *)buf;
iphdrlen = sizeof(unsigned long) * (iphdr-h_lenver 0xf);
tcphdr = (TCP_HEADER*)(buf + iphdrlen);
//是否来自目标IP
if(iphdr-sourceIP != dest.sin_addr.s_addr) return false;
//序列号是否正确
if((ntohl(tcphdr-th_ack) != (SEQ+1)) (ntohl(tcphdr-th_ack) != SEQ)) return false;
//if(tcphdr-th_flag == 20)return true;
//SYN/ACK - 扫描到一个端口
if(tcphdr -th_flag == 18)
{
printf("\t%d\t open \n",ntohs(tcphdr-th_sport));
return true;
}
return true;
}
void usage(void)
{
printf("\t===================SYN portscaner======================\n");
printf("\t============gxisone@hotmail.com 2004/7/6===========\n");
printf("\tusage: synscan DomainName[IP] StartPort-EndPort\n");
printf("\tExample: synscan 1-139\n");
printf("\tExample: synscan 192.168.1.1 8000-9000\n");
}
DWORD WINAPI RecvThread(LPVOID para)//接收数据线程函数
{
int iErrorCode;
struct hostent *hp;
char RecvBuf[65535]={0};
sockListen = socket(AF_INET , SOCK_RAW , IPPROTO_IP);
CheckSockError(sockListen, "socket");
//设置IP头操作选项
BOOL bOpt = true;
iErrorCode = setsockopt(sockRaw,IPPROTO_IP,IP_HDRINCL,(char *)bOpt,sizeof(bOpt));
CheckSockError(iErrorCode, "setsockopt()");
//获得本地IP
SOCKADDR_IN sa;
unsigned char LocalName[256];
iErrorCode = gethostname((char*)LocalName,sizeof(LocalName)-1);
CheckSockError(iErrorCode, "gethostname()");
if((hp = gethostbyname((char*)LocalName)) == NULL)
{
CheckSockError(SOCKET_ERROR, "gethostbyname()");
}
memcpy(sa.sin_addr.S_un.S_addr,hp-h_addr_list[1],hp-h_length);
sa.sin_family = AF_INET;
sa.sin_port = htons(7000);
iErrorCode = bind(sockListen, (PSOCKADDR)sa, sizeof(sa));
CheckSockError(iErrorCode, "bind");
//设置SOCK_RAW为SIO_RCVALL,以便接收所有的IP包
DWORD dwBufferLen[10] ;
DWORD dwBufferInLen = 1 ;
DWORD dwBytesReturned = 0 ;
iErrorCode=WSAIoctl(sockListen, SIO_RCVALL,dwBufferInLen, sizeof
(dwBufferInLen),dwBufferLen, sizeof(dwBufferLen),dwBytesReturned , NULL , NULL );
CheckSockError(iErrorCode, "Ioctl");
memset(RecvBuf, 0, sizeof(RecvBuf));
//接收数据
for(;;)
{
iErrorCode = recv(sockListen, RecvBuf, sizeof(RecvBuf), 0);
//CheckSockError(iErrorCode, "recv");
DecodeIPHeader(RecvBuf,iErrorCode) ;
}
if(ScanOK)
{
closesocket(sockListen);
return 0;
}
}
void playx(void) // 定义状态提示函数
{
// 进度条
char *plays[12]=
{
" | ",
" / ",
" - ",
" \\ ",
" | ",
" / ",
" - ",
" \\ ",
" | ",
" / ",
" - ",
" \\ ",
};
printf(" =%s=\r", plays[play]);
play=(play==11)?0:play+1;
Sleep(2);
}
//主函数
int main(int argc,char **argv)
{
char *p;
if(argc!=3)
{
usage();
return 0;
}
p=argv[2];//处理端口参数
if(strstr(argv[2],"-"))
{ DEST_PORT=atoi(argv[2]);
for(;*p;)
if(*(p++)=='-')break;
DEST_PORTEND=atoi(p);
if(DEST_PORT1 || DEST_PORTEND65535)
{ printf("Port Error!\n");
return 0;
}
}
DEST_HOST=argv[1];
usage();
int iErrorCode;
int datasize;
struct hostent *hp;
IP_HEADER ip_header;
TCP_HEADER tcp_header;
char SendBuf[128]={0};
//初始化SOCKET
WSADATA wsaData;
iErrorCode = WSAStartup(MAKEWORD(2,2),wsaData);
CheckSockError(iErrorCode, "WSAStartup()");
sockRaw = socket(AF_INET , SOCK_RAW , IPPROTO_IP);
CheckSockError(sockRaw, "socket()");
sockListen = socket(AF_INET , SOCK_RAW , IPPROTO_IP);
CheckSockError(sockListen, "socket");
//设置IP头操作选项
BOOL bOpt = true;
iErrorCode = setsockopt(sockRaw,IPPROTO_IP,IP_HDRINCL,(char *)bOpt,sizeof(bOpt));
CheckSockError(iErrorCode, "setsockopt()");
//获得本地IP
SOCKADDR_IN sa;
unsigned char LocalName[256];
iErrorCode = gethostname((char*)LocalName,sizeof(LocalName)-1);
CheckSockError(iErrorCode, "gethostname()");
if((hp = gethostbyname((char*)LocalName)) == NULL)
{
CheckSockError(SOCKET_ERROR, "gethostbyname()");
}
memcpy(sa.sin_addr.S_un.S_addr,hp-h_addr_list[1],hp-h_length);
sa.sin_family = AF_INET;
sa.sin_port = htons(7000);
iErrorCode = bind(sockListen, (PSOCKADDR)sa, sizeof(sa));
CheckSockError(iErrorCode, "bind");
//获得目标主机IP
memset(dest,0,sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_port = htons(DEST_PORT);
if((dest.sin_addr.s_addr = inet_addr(DEST_HOST)) == INADDR_NONE)
{
if((hp = gethostbyname(DEST_HOST)) != NULL)
{
memcpy((dest.sin_addr),hp-h_addr_list[1],hp-h_length);
dest.sin_family = hp-h_addrtype;
printf("dest.sin_addr = %s\n",inet_ntoa(dest.sin_addr));
}
else
{
CheckSockError(SOCKET_ERROR, "gethostbyname()");
}
}
//开启监听线程
HANDLE Thread=CreateThread(NULL,0,RecvThread,0,0,0);
//填充IP首部
ip_header.h_lenver=(44 | sizeof(ip_header)/sizeof(unsigned long));
//高四位IP版本号,低四位首部长度
ip_header.total_len=htons(sizeof(IP_HEADER)+sizeof(TCP_HEADER)); //16位总长度(字节)
ip_header.ident=1; //16位标识
ip_header.frag_and_flags=0; //3位标志位
ip_header.ttl=128; //8位生存时间TTL
ip_header.proto=IPPROTO_TCP; //8位协议(TCP,UDP…)
ip_header.checksum=0; //16位IP首部校验和
ip_header.sourceIP=sa.sin_addr.s_addr; //32位源IP地址
ip_header.destIP=dest.sin_addr.s_addr; //32位目的IP地址
//填充TCP首部
tcp_header.th_sport=htons(7000); //源端口号
tcp_header.th_lenres=(sizeof(TCP_HEADER)/44|0); //TCP长度和保留位
tcp_header.th_win=htons(16384);
//填充TCP伪首部(用于计算校验和,并不真正发送)
psd_header.saddr=ip_header.sourceIP;
psd_header.daddr=ip_header.destIP;
psd_header.mbz=0;
psd_header.ptcl=IPPROTO_TCP;
psd_header.tcpl=htons(sizeof(tcp_header));
Sleep(500);
printf("\n");
printf("Scaning %s\n",DEST_HOST);
start=clock();//开始计时
for(;DEST_PORTDEST_PORTEND;DEST_PORT++)
{
playx();
tcp_header.th_dport=htons(DEST_PORT); //目的端口号
tcp_header.th_ack=0; //ACK序列号置为0
tcp_header.th_flag=2; //SYN 标志
tcp_header.th_seq=htonl(SEQ); //SYN序列号
tcp_header.th_urp=0; //偏移
tcp_header.th_sum=0; //校验和
//计算TCP校验和,计算校验和时需要包括TCP pseudo header
memcpy(SendBuf,psd_header,sizeof(psd_header));
memcpy(SendBuf+sizeof(psd_header),tcp_header,sizeof(tcp_header));
tcp_header.th_sum=checksum((USHORT *)SendBuf,sizeof(psd_header)+sizeof(tcp_header));
//计算IP校验和
memcpy(SendBuf,ip_header,sizeof(ip_header));
memcpy(SendBuf+sizeof(ip_header),tcp_header,sizeof(tcp_header));
memset(SendBuf+sizeof(ip_header)+sizeof(tcp_header),0,4);
datasize=sizeof(ip_header)+sizeof(tcp_header);
ip_header.checksum=checksum((USHORT *)SendBuf,datasize);
//填充发送缓冲区
memcpy(SendBuf,ip_header,sizeof(ip_header));
//发送TCP报文
iErrorCode=sendto(sockRaw,SendBuf,datasize,0,(struct sockaddr*) dest,
sizeof(dest));
CheckSockError(iErrorCode, "sendto()");
}
end=clock();//计时结束
ScanOK=TRUE;
printf("Closeing Thread.....\n");
WaitForSingleObject(Thread,5000);
CloseHandle(Thread);
costtime= (float)(end - start) / CLOCKS_PER_SEC; //转换时间格式
printf("Cost time:%f Sec",costtime);//显示耗时
//退出前清理
if(sockRaw != INVALID_SOCKET) closesocket(sockRaw);
WSACleanup();
return 0;
}
求助网络编程题目.C++
一.概述
TCP/IP协议是一个四层协议,它由应用层、传输层、网络层和链路层构成。TCP/IP协议栈的每一层都由许多协议构成,从而构成了一个协议簇。
应用层主要包括的协议有Telnet、FTP、HTTP、SMTP/POP3和DNS等。
传输层主要包括的协议有TCP和UDP。
网络层主要包括IP和IP的附属协议。
数据链路层主要包括的协议有ARP(地址解析协议)、RARP协议、Ethernet协议等。
FTP(File Transfer Protocol)协议主要用来在网络上进行文件传输。FTP通讯除了有一个默认的端口21外,还有其他端口,同城两个端口同时进行数据传输。一个是默认的端口(通常为21),主要进行控制连接,即进行命令协议及服务器端响应码的传输。另一个非标准端口主要进行数据,上传下载文件等。
关于FTP协议和FTP命令的详细描述,参考《Visual C 网络通信编程实用案例精选》。
实现FTP协议,有两种方式,实用WinInet API和使用基本Winsock。对于一般应用,用WinInet效率要高,而且简单。也可以用Winsock来编写,这样更加灵活,但是复杂度高且需要对协议非常熟悉。
二.VC开发
在项目中,为了开发效率,使用了WinInet的方式。
FTP是MFC的WinInet支持的三个Internet功能(HTTP, gopher)之一,我们需要先创建一个CInternetSession实例和一个CFtpConnection对象就可以实现和一个 FTP服务器的通信。不需要直接创建CFtpConnection对象,而是通过调用CInternetsession::GetFtpConnection来完成这项工作。它创建CFtpConnection对象并返回一个指向该对象的指针。
要联接到FTP服务器,需要两个步骤,首先必须创建一个CInternetSession对象,用类CInternetSession创建并初始化一个或几个同时存在的Internet会话(session),并描述与代理服务器的连接(如果有必要的话),如果在程序运行期间需要保持与Internet的连接,可以创建一个CInternetsession对象作为类CWinApp的成员。
然后利用CInternetsession对象获取CFtpConnection对象。MFC中的类CFtpConnection管理我们与Internet服务器的连接,并直接操作服务器上的目录和文件。
1.Ftp连接类的信息
下面我们简要介绍连接类的信息
1.1 建立连接
CInternetsession对象
CInternetsession(LPCTSTR pstrAgent, DWORD dwConText, DWORD dwACCESSType, LPCTSTR pstrProxyName, LPCTSTR pstrProxyBypass, DWORD dwFlags);
在创建CInternetSession对象时调用这个成员函数,CInternetsession是应用程序第一个要调用的Internet函数,它将创始化内部数据结构,以备将来在应用程序中调用。如果dwFlags包含INTERNET_FLAG_ASYNC,那末从这个句柄派生的所有的句柄,在状态回调例程注册之前,都会出现异步状态。如果没有打开Internet连接,CInternetsession就会抛出一个例外,AfxThrowInternetException。
GetFtpConnection()函数
CFtpConnection* CIternetsession::GetFtpConnection(LPCTSTR pstrServer, LPCTSTR pstrUserName, LPCTSTR pstrPassword, INTERNET_PORT nPort, BOOL bPassive);
调用这个函数建立一个FTP连接,并获得一个指向CFtpConnection对象的指针,GetFtpConnection连接到一个FTP服务器,创建并返回指向CFtpConnection对象的指针,它不在服务器上进行任何操作。如果打算读写文件,必须进行分步操作。关于查找,打开和读写文件的信息需参考CFtpConnection和CFtpFileFind类。
对这个函数的调用返回一个指向CFtpConnection对象的指针。如果调用失败,检查抛出的CInternetException对象,就可以确定失败的原因。
1.2 远程目录操作
CreateDirectory()函数
BOOL CreateDirectory( LPCTSTR pstrDirName );
Return Value
Nonzero if successful; otherwise 0. If the call fails, the Windows functionGetLastError may be called to determine the cause of the error.
Parameters
pstrDirName
A pointer to a string containing the name of the directory to create.
Remarks
Call this member function to create a directory on the connected server.
Use GetCurrentDirectory to determine the current working directory for this connection to the server. Do not assume that the remote system has connected you to the root directory.
The pstrDirName parameter can be either a partially or a fully qualified filename relative to the current directory. A backslash (\) or forward slash (/) can be used as the directory separator for either name. CreateDirectory translates the directory name separators to the appropriate characters before they are used.
注意:CreateDir 在FTP服务器上创建已经存在的文件夹时会 返回FALSE,而且只能创建到当前(根)目录下
RemoveDirectory()函数
BOOL RemoveDirectory( LPCTSTR pstrDirName );
Return Value
Nonzero if successful; otherwise 0. If the call fails, the Win32 functionGetLastError may be called to determine the cause of the error.
Parameters
pstrDirName
A pointer to a string containing the directory to be removed.
Remarks
Call this member function to remove the specified directory from the connected server.
Use GetCurrentDirectory to determine the server’s current working directory. Do not assume that the remote system has connected you to the root directory.
The pstrDirName parameter can be either a partially or fully qualified filename relative to the current directory. A backslash (\) or forward slash (/) can be used as the directory separator for either name. RemoveDirectory translates the directory name separators to the appropriate characters before they are used.
注意:DeleteDir文件夹中有内容,先删除文件夹中文件,才可以删文件夹,否则返回FALSE, 删除不存在的文件夹返回FALSE
1.3 文件上传下载删除
GetFile()函数
BOOL GetFile(LPCTSTR pstrRemoteFile, LPCTSTR pstrLocalFile, BOOL bFailExists, DWORD dwAttributes, DWORD dwFlags, DWORD dwContext);
调用这个成员函数,可以从FTP服务器取得文件,并且把文件保存在本地机器上。GetFile()函数是一个比较高级的例程,它可以处理所有有关从FTP服务器读文件,以及把文件存放在本地机器上的工作。如果dwFlags为 FILE_TRANSFER_TYPE_ASCII,文件数据的传输也会把控制和格式符转化为Windows中的等阶符号。默认的传输模式是二进制模式,文件会以和服务器上相同的格式被下载。
pstrRemoteFile和 pstrLocalFile可以是相对于当前目录的部分文件名,也可以是全文件名,在这两个名字中间,都既可以用反斜杠(\)或者正斜杠(/)来作为文件名的目录分隔符,GetFile()在使用前会把目录分隔符转化为适当的字符。
可以用自己选择的值来取代dwContext默认的值,设置为上下文标识符与CFtpConnection对象的定位操作有关,这个操作由CFtpConnection中的CInternetSession对象创建。返回给CInternetsession::OnStatusCallBack的值指出了所标识操作的状态。
如果调用成功,函数的返回为非0,否则返回0,如果调用失败,可以调用Win32函数GetLastError(),确认出错的原因。
需要注意:本地路径须为绝对路径,远程路径可为相对路径,如hello/hello.zip,如果本地文件已经存在,则返回FALSE。
PutFile()函数
BOOL PutFile(LPCTSTR pstrLocalFile, LPCTSTR pstrRemoveFile ,DWORD dwFlags, DWORD dwContext);
调用这个成员函数可以把文件保存到FTP服务器。PutFile()函数是一个比较高级的例程,它可以处理有关把文件存放到服务器上的工作。只发送数据,或要严格控制文件传输的应用程序,应该调用OpenFile和 CInternet::Write。利用自己选择的值来取代dwContext默认的值,设置为上下文标识符,上下文标识符是 CInternetSession对象创建的CFtpConnection对象的特定操作有关,这个值返回给CInternetsession::OnStateCallBack,从而把操作的状态通报给它所标识的上下文。
如果调用成功,函数的返回为非0,否则返回0,如果调用失败,可以调用Win32函数GetLastError(),确认出错的原因。
主要注意:如果重复上传文件,会把服务器上的文件覆盖掉,且可以上传特定文件夹下,如hello/hello.zip
Remove()函数
BOOL Remove( LPCTSTR pstrFileName );
如果调用成功,函数的返回为非0,否则返回0,如果调用失败,可以调用Win32函数GetLastError(),确认出错的原因。
pstrFileName
需要删除的服务器上的文件名
Call this member function to delete the specified file from the connected server.
The pstrFileName parameter can be either a partially qualified filename relative to the current directory or fully qualified. A backslash (\) or forward slash (/) can be used as the directory separator for either name. The Remove function translates the directory name separators to the appropriate characters before they are used.
注意:Remove如果删除的文件不存在,则返回FALSE,支持相对路径
2. 测试实例
2.1 例一 连接到FTP站点
建立连接到的程序,它是一个单文档程序。并且连接由视图类的构造函数完成。
建立单文档程序ftp
在ftpview.h中加入包含#include afxinet.h
在ftpview.h中添加如下的成员变量
public:
CInternetSession *m_pInetsession;
CFtpConnection *m_pFtpConnection;
在ftpview.cpp中的ftpview构造函数中加入下面的代码
CFtpView::CFtpView()
{
m_pInetSession=new CInternetsession
(AfxGetAppName(),1,
PRE_CONFIG_INTERNET_ACCESS);
try
{
m_pFtpConnection=m_pInetsession-
GetFtpConnection("");
}
catch(CInternetException *pEx)
{
TCHAR szError[1024];
if(pEx-GetErrorMessage(szError,1024))
AfxMessageBox(szError);
else
AfxMessageBox("There was an exception");
pEx-Delete();
m_pFtpConnection=NULL;
}
}
在ftpview.cpp中的ftpview析构函数中加入下面的代码
CFtpView::~CFtpView()
{
if(m_pFtpConnection!=NULL)
{
m_pFtpConnection-Close();
delete m_pFtpConnection;
}
delete m_pInetsession;
}
编译并且执行程序,如果连接出现问题,将会在一个消息框中报告出错消息。
2.2 例二 发送文件到FTP文件服务器
创建一个发送文件到FTP文件服务器的程序
建立单文档程序ftpfw, 在ftpfwview.h中加入包含 #include afxinet.h
在ftpfwview.h中添加如下的成员变量
public:
bool m_bConnectionAttempted;
int m_nFileStatus;
在ftpview.cpp中的ftpview构造函数中加入下面的代码
CFtpfwView::CFtpfwView()
{
m_bConnectionAttempted=false;
}
使用ClassWizard加入新的类CFtpThread,该类派生于CWinThread 在ftpthread.h中加入如下变量
public:
static UINT PutFile(LPVOID Status);
添加新类成员函数代码
UINT CFtpThread::PutFile(LPVOID Status)
{
int *pnFileStatus;
CInternetSession *pInetsession;
CFtpConnection *pFtpConnection=NULL;
pnFileStatus=(int *)Status;
*pnFileStatus=0;
pInetsession=new CInternetsession(AfxGetAppName(),1,
PRE_CONFIG_INTERNET_ACCESS);
try
{
pFtpConnection=pInetsession-
GetFtpConnection("192.34.45.0");
}
catch(CInternetException *pEx)
{
pEx-Delete();
pFtpConnection=NULL;
*pnFileStatus=-1;
goto BallOut;
}
*pnFileStatus =1;
pFtpConnection-Remove("test.txt");
if(!pFtpConnection-PutFile
("test.txt","test.txt"))
*pnFileStatus=-2;
else
*pnFileStatus=2;
BallOut:
if(pFtpConnection!=NULL)
{
pFtpConnection-Close();
delete pFtpConnection;
}
delete pInetsession;
AfxEndThread(0);
return false;
}
编辑ftpfwview.cpp中的OnDraw()函数
void CFtpfwView::OnDraw(CDC* pDC)
{
CFtpfwDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if(!m_bConnectAttempted)
{
m_bConnectAttempted=TRUE;
AfxBeginThread((AFX_THREADPROC)
CFtpThread::PutFile,m_nFileStatus);
}
}
编译并且执行程序,在连接和传输的过程中,应用程序仍然可以作自己的工作,这是因为传输的过程发生在线程中。
3.封装FTPTransfer类
3.1 头文件
///////////////////////////////////////////////////////////
// FTPTransfer.h
// interface of the FTPTransfer module
// Created on: 24-July-2010
// Original author: Andrew Zhang
///////////////////////////////////////////////////////////
#ifndef _FTPTRANSFER_H_
#define _FTPTRANSFER_H_
#include afxinet.h // for ftp api functions
class FTPTransfer
{
public:
FTPTransfer();
~FTPTransfer();
BOOL Login();
void Logout();
BOOL CreateRemoteDir(LPCTSTR pstrDirName);
BOOL DeleteRemoteDir(LPCTSTR pstrDirName);
BOOL Upload(LPCTSTR pstrLocalFile, LPCTSTR pstrRemoteFile);
BOOL Download(LPCTSTR pstrRemoteFile, LPCTSTR pstrLocalFile);
BOOL DeleteRemoteFile(LPCTSTR pstrFileName);
BOOL UploadAll();
CString GetLastError();
protected:
private:
void Config();
CString m_csServer;
CString m_csUsername;
CString m_csPassword;
unsigned int m_nPort;
CInternetSession *m_pSession;
CFtpConnection *m_pConn;
static CString lastError;
public:
// 需要传输的文件夹
CStringArray m_astrAllDirName;
CString m_csLocalDir; // 本地图像所在路径,需要外界赋值。
};
#endif
3.2 设置配置项
可以配置服务器的IP,Port,用户名,密码等
配置项样例:
[FTPTransfer]
FTPServer = 192.168.29.253
Username = andrew
Password = zhang
Port = 21
;Ftp服务器的IP 账户 密码
3.3 使用说明
FTPTransfer transfer;
transfer.m_csLocalDir = url + strImgNo.c_str();
transfer.m_astrAllDirName.Add(csImgNo);
try
{
if (!transfer.UploadAll())
{
CString strlog(_T("[threadOperationTransfer]: "));
ServiceLog.write_log("[threadOperationTransfer]: ERROR! Upload error.");
CString csError = transfer.GetLastError();
ServiceLog.write_log((LPCWSTR)(strlog+ csError));
return -1; // FTP Error;
}
}
catch (...)
{
CString strlog(_T("[threadOperationTransfer]: "));
ServiceLog.write_log("[threadOperationTransfer]: ERROR! upload except:");
CString csError = transfer.GetLastError();
ServiceLog.write_log((LPCWSTR)(strlog+ csError));
return -1;
}
三.总结
通过以上的程序我们可以明白FTP的工作原理,因为基于应用,解释的还比较浅显。另外上传和下载需要比较久的时间,可以考虑设计多线程的方式来实现,这样不至于程序阻塞。
本文来自CSDN博客,转载请标明出处:

请给一些Windows中网络编程的资料
为一个不断进取的编程者,我们常常不满足于编程语言所提供的一般功能,总是希望能够实现一些特殊的功能,这有时不但是我们程序的要求,有时也是编程者心理上需要(试想,还会有什么比在深夜中巧妙解决一个难题而更令人兴奋呢?)。VisualBasic,做为一个当前最流行的快速编程环境,就给我们提供了实现这些目标的平台,事实上,它无限扩展的API接口可以实现所有WINDOWS下可以实现的功能。然而对于初学者来说,“浩瀚“的API函数总是显得那么神奇与不可琢磨,因此在实际应用过程中不能够灵活应用。下面我将结合两个小例子来示范介绍VB中调用API函数的步骤和功能,并总结说明在实际工作中如何提高这方面的技巧。例子在WINDOWS98下采用VB6.0编译。
一.限制鼠标的移动
---- 有时我们的软件要求用户在未完成某一任务时,鼠标不能移出当前活动控件,换句话就是将鼠标限制在控件的内部,直到任务完成或用户中断为止。这个功能借助API函数实现起来思路很清楚,代码也很简洁。其思路是先确定当前鼠标的位置;然后确定当前活动控件的大小;最后将鼠标限制在活动控件内。(下面忽略项目建立等过程)
---- 1.建立一个新项目:新窗体为form1,在form1上添加一个commandbutton,设置其Name=CMButton1;Caption=“将鼠标限制在此按钮中“
---- 2.拷贝API函数和POINTAPI结构:打开VB6.0自带的API浏览器,调入WIN32API.txt文件,复制以下结构和函数声明到form1的声明部分:
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Private Type POINTAPI
x As Long
y As Long
End Type
Private Declare Function ClientToScreen Lib
“user32“ Alias “ClientToScreen“ (ByVal
hwnd As Long, lpPoint As POINTAPI) As Long
‘用来确定当前鼠标的位置
Private Declare Function ClipCursor Lib
“user32“ Alias “ClipCursor“ (lpRect As Any)
As Long ‘用来限定当前鼠标的活动范围
---- 3.定义一个通用过程ConfineTo
Public Sub ConfineTo (myCtl As Object)
On Error Resume Next
Dim tmpRect As RECT
Dim pt As POINTAPI
With myCtl
If TypeOf myCtl Is Screen Then ‘锁定在屏幕范围内
tmpRect.Left = 0
tmpRect.Top = 0
tmpRect.Right = (.Width \ Screen.TwipsPerPixelX)
tmpRect.Bottom = (.Height \ Screen.TwipsPerPixelY)
Elseif TypeOf myCtl Is form ‘锁定在窗体范围内
tmpRect.Left = (.Left \ Screen.TwipsPerPixelX)
tmpRect.Top = (.Top \ Screen.TwipsPerPixelY)
tmpRect.Right = (.Left + .Width) \ Screen.TwipsPerPixelX
tmpRect.Bottom = (.Top + .Height) \ Screen.TwipsPerPixelY
else
pt.X = 0
pt.Y = 0
Call ClientToScreen(.hWnd, pt)
‘获取当前控件在屏幕上的位置
tmpRect.Left = pt.X
‘保存当前控件位置
tmpRect.Top = pt.Y
pt.X = .Width
pt.Y = .Height
Call ClientToScreen(.hWnd, pt)
tmpRect.Bottom = pt.Y
tmpRect.Right = pt.X
End If
Call ClipCursor(tmpRect)
End With
End Sub
---- 4.在 CMButton1_Click()中加入以下代码
Static Cliped As Boolean
‘静态变量用来控制状态切换
If Not Cliped Then
ConfineTo Cmbutton1
Cliped = True
Else
ConfineTo Screen ‘取消鼠标限制
Cliped = True
End If
---- 5. 运行后,鼠标点击cmbutton1,此时鼠标只能被锁定在此按钮内部,再次点击按钮,限制取消。
二.创建临时文件
---- 临时文件用来保存软件运行过程中的临时变化,这对于熟悉WORD等软件的人来说,经常会遇到。那么临时文件是如何产生的呢,其实很简单,只需要一个API函数就可以。
---- 1.拷贝声明函数(方法同前)
Private Declare Function GetTempFileName Lib “kernel32“ _
Alias “GetTempFileNameA“ (ByVal lpszPath As String, _
ByVal lpPrefixString As String, ByVal wUnique As Long, _
ByVal lpTempFileName As String) As Long
参数定义如下:
lpszPath =传入保存临时文件的路径 ,如“C:\mytemp“
lpPrefixString=传入临时文件名开始的前三个字母,
起到帮助识别临时文件来源的作用。
wUnique =0 ,windows随机产生文件名;否则安其值定义文件名。
lpTempFileName=返回随机文件名
---- 2.返回临时文件名
Private Function GenTempName(sPath As String)
Dim sPrefix As String
Dim lUnique As Long
Dim sTempFileName As String
If IsEmpty(sPath) Then sPath = “c:\temp“
sPrefix = “TVB“
lUnique = 0 ‘windows随机给名
sTempFileName = Space$(100)
GetTempFileName sPath, sPrefix, lUnique, sTempFileName
sTempFileName = Mid$(sTempFileName, 1,
InStr(sTempFileName, Chr$(0)) - 1) ‘去掉多余空格
GenTempName = sTempFileName
End Function
---- 3.将下面代码加入到form1_click()事件中
MsgBox GenTempName(“c:\temp“)
---- 4.运行,鼠标点击form,弹出msgbox,显示生成“c:\temp\TVB724.tmp“文件,用文件管理器查看,在c:\temp下有TVB724.tmp 文件,长度为0K。
---- 需要注意的是,传入的路径必须是有效路径,否则GenTempName函数返回0,lpTempFileName中也没有临时文件名。
三.结束语
---- 从上面可以看出,API函数的确简单高效,但也充满一些看似高深的变量而使人却步。我们不禁会问,究竟什么时候要用到API函数?具体哪些函数可以解决我的问题?,那些函数中的变量都代表什么?其实对这些问题,即使对一个VB高手也难给出明确的回答,因为API函数库实在太庞大了,每一个人最终只能熟悉其中的一小部分(这也可能是调用API的文章层出不穷的原因吧)。总结自己的一点经验,我觉得应该注意以下几点。
---- 1.熟练掌握VB基本技巧,了解其所能所不能,这是最基本的要求。
---- 2.了解WINDOWS内部控制机理,这样对一些复杂的问题就可以逐步分析其调用机制,初步确定采用哪部分的API函数来解决问题。
---- 3.案头必备一本最新的VB版的WINDOWS API 大全,推荐机械工业出版社的 。书中给出了每一个VB可以调用的API函数的详细说明,可以帮助精确了解所需要的API函数的变量声明。
---- 4.多看别人的程序。报纸杂志,尤其是网上这方面的文章数不清。这是最快的方法。
---- 5.随用随查。永远不要在用不到的函数上浪费宝贵的时间
c#网络编程UDP例子
using?System;?
using?System.Net;?
using?System.Net.Sockets;?
using?System.Text;?
using?System.Threading;?
using?System.Windows.Forms;?
?namespace?UDPClient?
{?
????public?partial?class?frmUdp?:?Form?
????{?
????????private?UdpClient?sendUdpClient;?
????????private?UdpClient?receiveUpdClient;?
????????public?frmUdp()?
????????{?
????????????InitializeComponent();?
????????????IPAddress[]?ips?=?Dns.GetHostAddresses("");?
????????????tbxlocalip.Text?=?ips[2].ToString();?
????????????int?port?=?51883;?
????????????tbxlocalPort.Text?=?port.ToString();?
????????????tbxSendtoIp.Text?=?ips[2].ToString();?
????????????tbxSendtoport.Text?=?port.ToString();?
????????}?
?
????????//?接受消息?
????????private?void?btnReceive_Click(object?sender,?EventArgs?e)?
????????{?
????????????//?创建接收套接字?
????????????IPAddress?localIp?=?IPAddress.Parse(tbxlocalip.Text);?
????????????IPEndPoint?localIpEndPoint?=?new?IPEndPoint(localIp,?int.Parse(tbxlocalPort.Text));?
????????????receiveUpdClient?=?new?UdpClient(localIpEndPoint);?
?
?
????????????Thread?receiveThread?=?new?Thread(ReceiveMessage);?
????????????receiveThread.Start();?
????????}?
?
????????//?接收消息方法?
????????private?void?ReceiveMessage()?
????????{?
????????????IPEndPoint?remoteIpEndPoint?=?new?IPEndPoint(IPAddress.Any,?0);?
????????????while?(true)?
????????????{?
????????????????try?
????????????????{?
????????????????????//?关闭receiveUdpClient时此时会产生异常?
????????????????????byte[]?receiveBytes?=?receiveUpdClient.Receive(ref?remoteIpEndPoint);?
?
????????????????????string?message?=?Encoding.Unicode.GetString(receiveBytes);?
?
????????????????????//?显示消息内容?
????????????????????ShowMessageforView(lstbxMessageView,?string.Format("{0}[{1}]",?remoteIpEndPoint,?message));?
????????????????}?
????????????????catch?
????????????????{?
????????????????????break;?
????????????????}?
????????????}?
????????}?
?
????????//?利用委托回调机制实现界面上消息内容显示?
????????delegate?void?ShowMessageforViewCallBack(ListBox?listbox,?string?text);?
????????private?void?ShowMessageforView(ListBox?listbox,?string?text)?
????????{?
????????????if?(listbox.InvokeRequired)?
????????????{?
????????????????ShowMessageforViewCallBack?showMessageforViewCallback?=?ShowMessageforView;?
????????????????listbox.Invoke(showMessageforViewCallback,?new?object[]?{?listbox,?text?});?
????????????}?
????????????else?
????????????{?
????????????????lstbxMessageView.Items.Add(text);?
????????????????lstbxMessageView.SelectedIndex?=?lstbxMessageView.Items.Count?-?1;?
????????????????lstbxMessageView.ClearSelected();?
????????????}?
????????}?
????????private?void?btnSend_Click(object?sender,?EventArgs?e)?
????????{?
????????????if?(tbxMessageSend.Text?==?string.Empty)?
????????????{?
????????????????MessageBox.Show("发送内容不能为空","提示");?
????????????????return;?
????????????}?
?
????????????//?选择发送模式?
????????????if?(chkbxAnonymous.Checked?==?true)?
????????????{?
????????????????//?匿名模式(套接字绑定的端口由系统随机分配)?
????????????????sendUdpClient?=?new?UdpClient(0);?
????????????}?
????????????else?
????????????{?
????????????????//?实名模式(套接字绑定到本地指定的端口)?
????????????????IPAddress?localIp?=?IPAddress.Parse(tbxlocalip.Text);?
????????????????IPEndPoint?localIpEndPoint?=?new?IPEndPoint(localIp,?int.Parse(tbxlocalPort.Text));?
????????????????sendUdpClient?=?new?UdpClient(localIpEndPoint);?
????????????}?
?
????????????Thread?sendThread?=?new?Thread(SendMessage);?
????????????sendThread.Start(tbxMessageSend.Text);?
????????}?
?
????????//?发送消息方法?
????????private?void?SendMessage(object?obj)?
????????{?
????????????string?message?=?(string)obj;?
????????????byte[]?sendbytes?=?Encoding.Unicode.GetBytes(message);?
????????????IPAddress?remoteIp?=?IPAddress.Parse(tbxSendtoIp.Text);?
????????????IPEndPoint?remoteIpEndPoint?=?new?IPEndPoint(remoteIp,?int.Parse(tbxSendtoport.Text));?
????????????sendUdpClient.Send(sendbytes,?sendbytes.Length,?remoteIpEndPoint);?
???????????
????????????sendUdpClient.Close();?
????????????
????????????//?清空发送消息框?
????????????ResetMessageText(tbxMessageSend);?
????????}?
?
????????//?采用了回调机制?
????????//?使用委托实现跨线程界面的操作方式?
????????delegate?void?ResetMessageCallback(TextBox?textbox);?
????????private?void?ResetMessageText(TextBox?textbox)?
????????{?
????????????//?Control.InvokeRequired属性代表?
????????????//?如果空间的处理与调用线程在不同线程上创建的,则为true,否则为false?
????????????if?(textbox.InvokeRequired)?
????????????{?
????????????????ResetMessageCallback?resetMessagecallback?=?ResetMessageText;?
????????????????textbox.Invoke(resetMessagecallback,?new?object[]?{?textbox?});?
????????????}?
????????????else?
????????????{?
????????????????textbox.Clear();?
????????????????textbox.Focus();?
????????????}?
????????}?
?
????????//?停止接收?
????????private?void?btnStop_Click(object?sender,?EventArgs?e)?
????????{?
????????????receiveUpdClient.Close();?
????????}?
?
????????//?清空接受消息框?
????????private?void?btnClear_Click(object?sender,?EventArgs?e)?
????????{?
????????????this.lstbxMessageView.Items.Clear();?
????????}?
????}?
}