博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Windows网络编程
阅读量:6225 次
发布时间:2019-06-21

本文共 6887 字,大约阅读时间需要 22 分钟。

Windows网络编程使用winsock。Winsock是一个基于Socket模型的API,在Windows系统中广泛使用。

使用Winsock进行网络编程需要包含头文件Winsock2.h,需要使用库ws2_32.lib,包含方法:可以使用语句来告诉编译器连接该库
#pragma comment(lib, “ws2_32.lib”);
如果使用VS,可以通过“项目” --> “XX属性”--> “连接器”-->“输入”--> “附加依赖项”添加ws2_32.lib。 (XX为当前工程名)

面向连接的C/S程序工程流程图

使用Winsock API编制的网络应用程序中,在调用任何一个Winsock函数之前都必须检查协议栈安装情况,使用函数WSAStartup()完成操作。
● 一个服务端的例子

View Code
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);}

● 监听线程函数

View Code
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
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
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[i]) < 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[i] = -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;}

  一个客户端的例子

View Code
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 设置套接口的工作方式

转载地址:http://uxuna.baihongyu.com/

你可能感兴趣的文章
Activity那些不得不说的事
查看>>
小米生早了!!
查看>>
mysqldump: Got error: 1556: You can't use locks with log tables
查看>>
JS闭包
查看>>
Windows 管理PostgreSQL服务
查看>>
演讲实录 | Service Mesh 时代的选边与站队(附PPT下载)
查看>>
Eclipse 安装findbugs插件
查看>>
labview加密分析-1综述
查看>>
log4j自定义Appender
查看>>
部署公司后台管理系统中 关于jar包冲突的问题
查看>>
【九度OJ1367】|【剑指offer24】二叉搜索树的后序遍历序列
查看>>
JVM运行时内存结构
查看>>
MySQL数据库删除后的恢复工作
查看>>
转:wordpress样式修改
查看>>
我的友情链接
查看>>
仿新浪微博底部菜单TabHost
查看>>
【高清视频】CCNA系列课程之五:STP生成树协议介绍
查看>>
u盘 找不到应用程序
查看>>
Red hat samba不识别windows 下的中文
查看>>
MDT U盘自动部署报错解决办法
查看>>