网友评论
分类

大小:11.7 MB
语言:简体中文系统:WinXP, Win2003, Vista, Win7, Win8, Win10
类别:编程相关时间:2017-01-19
windows网络编程pdf是为学习编程的用户打造的一款辅助工具,包含详细的Winsock基础、Winsock I/O方法、客户端远程访问服务器、Windows重定向器等信息,大量实例解析网络API函数,可以满足中高级编程人员的需求。
windows网络编程系统性较强,内容丰富、结构清晰、论述严谨,既突出基本原理和技术思想,也强调工程实践,适合作为网络工程、信息安全、计算机应用、计算机软件、通信工程等专业的本科生教材,也可供从事网络工程、网络应用开发和网络安全等工作的技术人员参考。
● 面向连接的C/S程序工程流程图

使用Winsock API编制的网络应用程序中,在调用任何一个Winsock函数之前都必须检查协议栈安装情况,使用函数WSAStartup()完成操作。
● 一个服务端的例子
void server::startServer()
{
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested=MAKEWORD(2,2);
if(WSAStartup(wVersionRequested,&wsaData)!=0)
{
//Winsock初始化错误
msgBox.exec();
return;
}
if(wsaData.wVersion!=wVersionRequested)
{
//Winsock版本不匹配
WSACleanup();
return;
}
if ((m_sk = socket(AF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR)
{
WSACleanup();
return;
}
bool ok;
unsigned short port = ui.portLineEdit->text().toInt(&ok, 10);
if (ok == false)
{
//端口输入错误
closesocket(m_sk);
m_sk = -1;
WSACleanup();
return;
}
sockaddr_in addr;
addr.sin_family = AF_INET; //使用互联网际协议,即IP协议
addr.sin_port = htons(port);
addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
if (bind(m_sk, (sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR)
{
//绑定端口失败
closesocket(m_sk);
m_sk = -1;
WSACleanup();
return;
}
if (listen(m_sk, 10) == SOCKET_ERROR)
{
//监听端口失败
closesocket(m_sk);
m_sk = -1;
WSACleanup();
return;
}
updateMsgRecs(tr("等待连接..."));
//创建线程去等待连接
HANDLE h = CreateThread(NULL, 0, &server::acceptProc, (LPVOID)this, 0, 0);
if (h == NULL)
{
closesocket(m_sk);
m_sk = -1;
WSACleanup();
return;
}
CloseHandle(h);
}
● 监听线程函数
DWORD WINAPI server::acceptProc(LPVOID lpParamter)
{
/*server *p_server = (server *)lpParamter;
sockaddr_in client_addr;
int len = sizeof(client_addr);
char msgBuff[256];
int sk;
while (1)
{
if ((sk = ::accept(p_server->sk(), (sockaddr*)&client_addr, &len) )== SOCKET_ERROR)
{
emit p_server->haveNewMsg(QObject::tr("accept 出错"));
break;
}
sprintf(msgBuff, "新连接来自%s", inet_ntoa(client_addr.sin_addr));
emit p_server->haveNewMsg(msgBuff);
emit p_server->newClient(inet_ntoa(client_addr.sin_addr), sk);
}*/
server *p_server = (server *)lpParamter;
int client[FD_SETSIZE];
fd_set allset, rset;
sockaddr_in client_addr;
int len;
int clientfd;
int sockfd;
int i;
for (i=0; i<FD_SETSIZE; i++)
client = -1;
FD_ZERO(&allset);
int listenfd = p_server->sk();
FD_SET(listenfd, &allset);
int nready;
int maxfd = listenfd;
int maxi = -1;
char buff[MAX_LEN+1];
while (1)
{
rset = allset;
nready = select(maxfd+1, &rset, NULL, NULL, NULL);
if (FD_ISSET(listenfd, &rset)) //new connection
{
len = sizeof(client_addr);
if ( (clientfd = ::accept(p_server->sk(), (sockaddr*)&client_addr, &len)) == SOCKET_ERROR)
{
emit p_server->haveNewMsg(QObject::tr("accept 出错"));
break;
}
//找出client数组中第一个为-1的单元存放已经连接的socket
for (i=0; i<FD_SETSIZE; i++)
{
if (client <0)
{
client = clientfd;
break;
}
}
if (i == FD_SETSIZE)
{
emit p_server->haveNewMsg(QObject::tr("error: too many clients!"));
break;
}
//sprintf(buff, "新连接来自%s", inet_ntoa(client_addr.sin_addr));
//emit p_server->haveNewMsg(buff);
emit p_server->newClient(inet_ntoa(client_addr.sin_addr), clientfd);
FD_SET(clientfd, &allset);
if (clientfd > maxfd)
maxfd = clientfd;
if (i>maxi)
maxi = i;
if (--nready <= 0)
continue;
}
for (i=0; i<=maxi; i++)
{
if ( (sockfd = client) < 0)
continue;
if (FD_ISSET(sockfd, &rset))
{
int n;
//客户端已经关闭连接
if ( (n = recv(sockfd, buff, MAX_LEN, 0 )) <= 0)
{
closesocket(sockfd);
FD_CLR(sockfd, &allset);
client = -1;
emit p_server->haveNewMsg(QObject::tr("client closed"));
emit p_server->sClientClose(sockfd);
}
else //收到数据
{
buff[n] = 0;
emit p_server->haveNewMsg( buff, sockfd);
if (--nready <= 0)
break;
}
}
} //for (i=0; i<=maxi; i++)
}
return 0;
}
● 一个客户端的例子
void client::connectServer()
{
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested=MAKEWORD(2,2);
if(WSAStartup(wVersionRequested,&wsaData)!=0)
{
//Winsock初始化错误
QMessageBox msgBox(QMessageBox::Warning, tr("错误"), tr("Winsock初始化错误"), QMessageBox::Ok, 0);
msgBox.exec();
return;
}
if(wsaData.wVersion!=wVersionRequested)
{
//Winsock版本不匹配
QMessageBox msgBox(QMessageBox::Warning, tr("错误"), tr("Winsock版本不匹配"), QMessageBox::Ok, 0);
msgBox.exec();
WSACleanup();
return;
}
if ((m_sk = socket(AF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR)
{
QMessageBox msgBox(QMessageBox::Warning, tr("错误"), tr("创建socket失败"), QMessageBox::Ok, 0);
msgBox.exec();
WSACleanup();
return;
}
sockaddr_in addr;
addr.sin_family = AF_INET;
bool ok;
unsigned short port = ui.portLineEdit->text().toInt(&ok, 10);
if (ok == false)
{
QMessageBox msgBox(QMessageBox::Warning, tr("错误"), tr("端口输入错误"), QMessageBox::Ok, 0);
msgBox.exec();
closesocket(m_sk);
m_sk = -1;
WSACleanup();
return;
}
addr.sin_port = htons(port);
addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
if (0 == ::connect(m_sk, (sockaddr *)&addr, sizeof(addr)))
{
updateMsgRecs(tr("连接成功..."));
HANDLE h = CreateThread(NULL, 0, &client::recvProc, (LPVOID)this, 0, 0);
CloseHandle(h);
}
else
{
QMessageBox msgBox(QMessageBox::Warning, tr("错误"), tr("连接出错"), QMessageBox::Ok, 0);
msgBox.exec();
closesocket(m_sk);
m_sk = -1;
WSACleanup();
}
}
● winsock APIs
网络连接函数
socket 创建套接字
bind 绑定本机端口
connect 建立连接
listen 监听端口
accept 接受连接
recv, recvfrom 数据接收
send, sendto 数据发送
close, shutdown 关闭套接字
转换函数
inet_addr() 点分十进制数表示的IP地址转换为网络字节序的IP地址
inet_ntoa() 网络字节序的IP地址转换为点分十进制数表示的IP地址
字节顺序转换函数
htonl 4字节主机字节序转换为网络字节序
ntohl 4字节网络字节序转换为主机字节序
htons 2字节主机字节序转换为网络字节序
ntohs 2字节网络字节序转换为主机字节序
网络信息检索函数
gethostname 获得主机名
getpeername 获得与套接口相连的远程协议地址
getsockname 获得套接口本地协议地址
gethostbyname 根据主机名取得主机信息
gethostbyaddr 根据主机地址取得主机信息
getprotobyname 根据协议名取得主机协议信息
getprotobynumber 根据协议号取得主机协议信息
getservbyname 根据服务名取得相关服务信息
getservbyport 根据端口号取得相关服务信息
getsockopt/setsockopt 获取/设置一个套接口选项
ioctlsocket 设置套接口的工作方式
目录
译者序
前言
第一部分 传统网络API
第1章 NetBIOS
第2章 重定向器
第3章 邮槽
第4章 命名管道
第二部分 Winsock API
第5章 网络原理和协议
第6章 地址家族和名字解析
第7章 Winsock基础
第8章 Winsock I/O方法
第9章 套接字选项和I/O控制命令
第10章 名字注册和解析
第11章 多播
第12章 常规服务质量
第13章 原始套接字
第14章 Winsock 2服务提供者接口
第15章 微软Visual Basic Winsock控件
第三部分 远程访问服务
第16章 RAS客户机
第四部分 附录录录
附录A NetBIOS命令索引
附录B IP助手函数
附录C Winsock错误代码
展开
猜您喜欢
网友评论