文章目录

  • 前言
  • 一、服务器
    • WSAStartup函数
      • 正常使用
      • 函数详解
    • socket函数
    • bind函数
    • listen函数
    • accept函数
    • send函数
    • recv函数
    • closesocket函数
    • WSACleanup函数
  • 二、客户端
    • connect函数
  • 三、其它网络相关函数
    • htons,ntohs等
    • inet_addr,inet_ntoa
    • gethostbyname
    • 注意事项

前言

对学习C/C++感兴趣的同学可以看看我的这篇文章哦:C/C++教程

相比于基础,网络编程就要复杂一些,但其实也有固定格式,记住即可。

首先是需要的头文件和库:

#include<WinSock2.h>
#pragma comment(lib,"ws2_32.lib")

一、服务器

主要流程及主要函数:

  1. 网络环境初始化:WSAStartup
  2. 创建服务器套接字:socket
  3. 绑定本机IP和端口:bind
  4. 监听客户端:listen
  5. 等待客户端连接:accept
  6. 发送消息:send
  7. 接收消息:recv
  8. 关闭socket:closesocket
  9. 清除网络环境:WSACleanup

WSAStartup函数

正常使用

函数原型:

int WSAStartup(
WORD wVersionRequested, //版本号,使用MAKEWORD宏生成
LPWSADATA lpWSAData //数据
);
//返回值:0代表成功,否则失败

使用方法:

#include<WinSock2.h>
#include<iostream>
#pragma comment(lib,"ws2_32")
using namespace std;
int main() {WSADATA data;int ret=WSAStartup(MAKEWORD(2,2),&data);if (ret) {cout << "初始化网络错误!" << endl;return -1;}
}

该函数用于初始化网络环境,参数基本上是固定写法,记住即可,必须要有。

函数详解

该函数实则是用来加载Windows Socket动态库的

wVersionRequested参数用来指定准备加载动态库的版本号,高字节为库文件的副版本,低字节指定主版本,MAKEWORD(X,Y)宏用于生成该参数,其中X为高字节,Y为低字节

lpWSAData 为指向WSADATA结构体的指针,该参数用于返回被加载动态库的有关信息

typedef struct WSAData {WORD            wVersion; //期望调用者使用的socket版本(或实际返回的socket版本,可根据此参数判断返回的版本号是否正确,可通过HIBYTE宏取得高字节,LOBYTE宏取得低字节)
WORD            wHighVersion; //本机Dll支持的最高版本
unsigned short  iMaxSockets;//一个进程最多可以打开的套接字数量(2.0版本后忽略此值)
unsigned short  iMaxUdpDg; //一个进程发送或接收的最大数据报长度
char FAR *      lpVendorInfo; //厂商专有信息(2.0版本后忽略此值)
char            szDescription[WSADESCRIPTION_LEN+1]; //DLL的描述信息
char            szSystemStatus[WSASYS_STATUS_LEN+1];//DLL的状态信息

socket函数

函数原型:

SOCKET socket(
int af, //地址类型,常用IPv4地址:AF_INET,和IPv6地址:AF_INET6
int type, //套接字类型,常用TCP协议:SOCK_STREAM,UDP协议:SOCK_DGRAM
int protocol //协议类型,一般填0,自动选择即可
);
//返回值,INVALID_SOCKET失败,该宏实则定义为-1,否则成功

使用:


SOCKET sock=socket(AF_INET,SOCK_STREAM,0);
if (sock == -1) {cout << "创建套接字失败";return -1;
}

该代码创建了IPv4类型的地址,TCP协议的套接字

完整视图:

bind函数

函数原型:

int bind(
SOCKET s, //创建的socket
sockaddr * name, //包含地址和端口的结构体
int namelen //sockaddr 结构长度
);
//返回值:返回SOCKET_ERROR失败,该宏被定义为-1,否则成功,返回值为0

使用:

#define _WINSOCK_DEPRECATED_NO_WARNINGS //vs环境下必须定义,否则无法使用inet_addr函数
sockaddr_in addr;
addr.sin_family = AF_INET; //地址为IPv4协议
addr.sin_port = htons(9999); //端口为9999
addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //具体绑定本机的地址
ret=bind(sock,(sockaddr*)&addr, sizeof(addr)); //绑定
if (ret == -1) {cout << "绑定地址端口失败";return -1;
}

完整视图:

listen函数

函数原型:

int listen(
SOCKET s, //要监听的socket
int backlog //等待连接的最大队列长度
);
//返回值:返回SOCKET_ERROR失败,该宏被定义为-1,否则成功,返回值为0

使用:

ret=listen(sock,5);
if (ret == -1) {cout << "监听套接字失败";return -1;
}

完成代码:

accept函数

函数原型:

SOCKET accept(
SOCKET s, //接收的socket
sockaddr* addr, //接收到客户端的地址信息
int * addrlen //地址信息长度
);
//返回值:返回INVALID_SOCKET失败,该宏定义为-1,否则成功返回客户端的套接字,可进行发送和接收消息

使用:

sockaddr addrCli;
int len = sizeof(addrCli);
SOCKET sockCli=accept(sock,&addrCli,&len);
if (sockCli == -1) {cout << "接收客户端连接失败";return -1;
}

完整代码视图:

send函数

函数原型:

int send(
SOCKET s,
char * buf,//要发送的内容
int len, //内容长度
int flags //一般为0,拷贝到程序中就立即删除内核中的数据,或MSG_DONTROUTE:要求传输层不要将数据路由出去,MSG_OOB:标志数据应该被带外发送
);
//返回值:-1(或宏SOCKET_ERROR)表示发送失败,否则返回发送成功的字节数

使用:

char buf[0xFF] = "我是服务器";
ret=send(sockCli, buf, strlen(buf),0);
if (ret == -1) {cout << "发送信息失败";
}

整体视图:

recv函数

函数原型:

int recv(
SOCKET s, //套接字char * buf, //接受数据的缓存区
int len, //缓存区大小
int flags //标志,一般填0,将消息拷贝到应用程序中,将内核中的数据删除,还可以填MSG_PEEK,只取数据,不从内核中删除数据,MSG_OOB:处理带外数据
);
//返回值:小于等于0都表示出错,大于0则表示接收成功的数据大小

使用:

ret=recv(sockCli,buf,0xFF,0);
if (ret <= 0) {cout << "接受客户端数据失败";return -1;
}

完整视图:

closesocket函数

int closesocket(
SOCKET s //要关闭的socket
);

该函数就是关闭不用的socket,释放资源

WSACleanup函数

无任何参数,直接调用即可

WSACleanup();

按理说尽量在应用程序退出时都要进行清理,否则下次启动可能出现错误

修改后的代码视图:

完整代码:

#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include<WinSock2.h>
#pragma comment(lib,"ws2_32")
#include<iostream>
using namespace std;
int main() {WSADATA data;int ret=WSAStartup(MAKEWORD(2,2),&data);if (ret) {cout << "初始化网络错误!" << endl;WSACleanup();return -1;}SOCKET sock=socket(AF_INET,SOCK_STREAM,0);if (sock == -1) {cout << "创建套接字失败";WSACleanup();return -1;}sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(9999);addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");ret=bind(sock,(sockaddr*)&addr, sizeof(addr));if (ret == -1) {cout << "绑定地址端口失败";WSACleanup();return -1;}ret=listen(sock,5);if (ret == -1) {cout << "监听套接字失败";WSACleanup();return -1;}sockaddr addrCli;int len = sizeof(addrCli);SOCKET sockCli=accept(sock,&addrCli,&len);if (sockCli == -1) {cout << "接收客户端连接失败";WSACleanup();return -1;}char buf[0xFF] = "我是服务器";ret=send(sockCli, buf, strlen(buf),0);if (ret == -1) {cout << "发送信息失败";WSACleanup();return -1;}ret=recv(sockCli,buf,0xFF,0);if (ret <= 0) {cout << "接受客户端数据失败";WSACleanup();return -1;}WSACleanup();
}

至此,一个最简单的windows服务器就写好了,可以简单执行一次发送数据和一次接受数据。

二、客户端

主要流程和函数:

  1. 初始化网络环境:WSAStartup
  2. 创建套接字:socket
  3. 连接服务器:connect
  4. 发送数据:send
  5. 接收数据:recv
  6. 清理网络环境:WSACleanup

其它三个函数与服务器一样,只是多出个connect函数,使用方法也与bind函数类似

connect函数

函数原型:

int connect(
SOCKET s, //与服务器连接的socket
sockaddr* name, //服务器的地址端口
int namelen //上个参数结构体的长度
);
//返回值:-1失败,否则成功

使用方法:

sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(9999);
addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
int ret = connect(sock, (sockaddr*)&addr, sizeof(addr));
if (ret == -1) {cout << "连接服务器失败" << endl;return -1;
}

完整代码视图:

完整代码:

#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include<WinSock2.h>
#include<iostream>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
int main() {WSADATA data;int ret = WSAStartup(MAKEWORD(2, 2), &data);if (ret) {cout << "初始化网络错误!" << endl;WSACleanup();return -1;}SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(9999);addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");int ret = connect(sock, (sockaddr*)&addr, sizeof(addr));if (ret == -1) {WSACleanup();cout << "连接服务器失败" << endl;return -1;}char buf[0xFF];ret=recv(sock,buf,sizeof(buf),0);if (ret <= 0) {WSACleanup();cout << "接收服务器数据失败" << endl;return -1;}cout << "服务器:" << buf << endl;ret=send(sock,buf,ret,0); //将接收到的数据发回服务器if (ret <= 0) {WSACleanup();cout << "发送服务器数据失败" << endl;return -1;}WSACleanup();
}

三、其它网络相关函数

htons,ntohs等

这种函数名有固定的意义:

  • h:home
  • n:network
  • s:short
  • l:long

htons:意思就是本机字节序转到网络字节序,short类型的长度
ntohs:意思就是网络字节序转到本机字节序,short类型的长度

还有htonl,htonll,htonf等也是类似的意思

inet_addr,inet_ntoa

  • inet_addr:负责将我们平时看到的网络地址127.0.0.1等转化为网络字节序
  • inet_ntoa:负责将网络字节序还原为我们平时看到的字符串127.0.0.1等

使用方法:

sockaddr_in addr;
addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //将127.0.0.1转换为网络字节序
char* c_IP = inet_ntoa(addr.sin_addr);//将网络字节序转换为127.0.0.1字符串

gethostbyname

通过域名获取ip地址,比如我们常见的www.baidu.com的ip地址是多少呢?就可以通过这个函数获取

使用方法:

//获取主机ip
HOSTENT* host = gethostbyname("www.baidu.com"); //如获取网站IP地址,参数填写域名即可,不需加"http://"
if (host == NULL)
{return false;
}
//转化为char*并拷贝返回
cout << inet_ntoa(*(in_addr*)*host->h_addr_list);

注意事项

这些函数都被微软定为不安全函数,想正常使用就必须在代码最前面定义宏:

#define _WINSOCK_DEPRECATED_NO_WARNINGS

C/C++网络编程详解(Windows版)相关推荐

  1. Linux网络编程---详解TCP

    Linux网络编程---详解TCP的三次握手和四次挥手_shanghx_123的博客-CSDN博客_tcp的协议数据单元被称为 TCP协议详解(TCP报文.三次握手.四次挥手.TIME_WAIT状态. ...

  2. python编程入门与案例详解-Pythony运维入门之Socket网络编程详解

    Socket是什么? Socket 是电脑网络中进程间数据流的端点Socket 是操作系统的通信机制应用程序通过Socket进行网络数据的传输 首先,简单了解一下TCP通信过程: TCP三次握手(面试 ...

  3. 初级游戏外挂编程详解 windows运行原理+游戏辅助编程 游戏外挂编程

    @TOC初级游戏外挂编程详解 windows运行原理+游戏辅助编程 游戏外挂编程 [1]什么是windows API Windows API 中文翻译过来就是windows应用程序接口(Applica ...

  4. Netty从使用到源码3_NIO网络编程详解

    关于BIO(即Java传统的网络编程,参考) NIO网络编程 1.逐步演变 1.单线程阻塞模式 创建服务器 import java.net.InetSocketAddress; import java ...

  5. python网络编程项目_python网络编程详解

    最近在看<UNIX网络编程 卷1>和<FREEBSD操作系统设计与实现>这两本书,我重点关注了TCP协议相关的内容,结合自己后台开发的经验,写下这篇文章,一方面是为了帮助有需要 ...

  6. unet网络python代码详解_python网络编程详解

    最近在看<UNIX网络编程 卷1>和<FREEBSD操作系统设计与实现>这两本书,我重点关注了TCP协议相关的内容,结合自己后台开发的经验,写下这篇文章,一方面是为了帮助有需要 ...

  7. android 网络编程实现,Android开发使用HttpURLConnection进行网络编程详解【附源码下载】...

    本文实例讲述了Android开发使用HttpURLConnection进行网络编程.分享给大家供大家参考,具体如下: --HttpURLConnection URLConnection已经可以非常方便 ...

  8. 14.网络编程详解-狂神笔记

    01.什么是计算机网络 网络编程 打电话 – 连接 – 接了电话 – 通话 (TCP) 发短信 – 发送了就完事了 – 接收 (UDP) 计算机网络: 计算机网络是指将地理位置不同的具有独立功能的多台 ...

  9. Linux 网络编程详解二(socket创建流程、多进程版)

    netstat -na | grep "8080" --查看TCP/IP协议连接状态 //socket编程提高版--服务器 #include <stdio.h> #in ...

  10. web中网络编程详解

    今天是冬至,不知道大家有没有吃饺子啊! 每日分享: 冬至是北半球一年之中夜晚最长的一天,愿你在这个长夜能融化掉这一年所有的不快乐!! 目录: IP地址的介绍 端口和端口号的介绍 TCP的介绍 sock ...

最新文章

  1. 学习笔记之Fluent Python
  2. html文字自动上翻,jQuery超酷文字随机翻转变换动画特效
  3. Verilog | HDL LCD显示(代码类)
  4. 面向对象设计原则-Principles and Patterns读书笔记三
  5. SQL Server数据库字段类型详解
  6. 我们每个人都想在事业上获得成功,但做到的人往往凤毛麟角
  7. linux命令ps -aux|grep xxx详解
  8. 【Q】CentOS-部署后,只有本机可以访问的问题
  9. AEJoy —— 表达式之弹性震动模拟详解【JS】
  10. 如何不授权情况下获取自己微信openid/傻瓜式获取
  11. 《会计学》的简单了解
  12. 生命礼赞,带动世界第三次文化复兴伊比利亚双雄篇
  13. centos7下显卡型号查询
  14. elementUI中折叠面板箭头图标位置调整
  15. 购买重疾险是不是都要先去体检?千万不要!
  16. 充电桩(charging station)是什么?
  17. android_app开发微信支付集成
  18. getsockopt
  19. vue引用DPlayer播放器
  20. CRM系统如何降低销售离职带来的损失?

热门文章

  1. 《Redis设计与实现》知识点目录
  2. 小程序源码:全新外卖侠cps5.6全套微信小程序源码下载(内附加2.7.5版本微擎)支持多种CPS收益和流量主收益
  3. win10下Miracast无线投屏使用教程及异常解决方案(超详细)
  4. 数据加载中...请稍后(js一句代码)
  5. 【Luyten反编译工具】
  6. 各省简称 拼音 缩写_省份简称拼音
  7. spss20安装许可证代码_SPSS 22下载安装教程
  8. 30+本MySQL经典书籍
  9. Redis基础--使用treeNMS管理及监控Redis
  10. 数据结构C语言版第二版答案 严蔚敏 李冬梅 吴伟民 编著