WinSock网络编程经络----读书笔记(3)
七、socket基本概念
1、简介
a、协议簇和地址簇
TCP/IP协议簇符号标识是PF_*,地址簇符号标识是AF_*。由于TCP/IP的协议簇只有一种地址簇,已有的实现都把他们定义为相同的值。
b、端口
能通过端口找到相应的进程
2、WinSocket和Berkeley socket的区别
3、WinSocket I/O模式
在WinSocket中主要有三种I/O操作模式:阻塞、非阻塞和重叠I/O。在默认情况下,Berkeley和WinSocket都是建立阻塞的socket。为了建立非阻塞的socket,应用程序使用ioctlsocket的FIONBIO命令把socket设置为非阻塞的。在创建socket中制定了重叠I/O属性时,才能使用重叠I/O功能
a、阻塞I/O
线程使用了一个recv调用,但socket上没有数据,线程将被阻塞,直到socket接收到数据,并把数据复制到线程接收函数提供的缓冲区中。阻塞I/O虽然简单,但他不是最有效的编程方式
b、非阻塞I/O
和上面的一个简单的区别就是应用程序使用select检测是否有数据刻度,如有则使用recv接收数据,确保recv不会阻塞
c、重叠I/O
这是在WinSocket2.0版本中新加的特征。发送数据时,程序可以连续多次调用发送函数提供多个数据缓冲区去排队输出数据。发送数据时,程序使用WSASend或WSASendTo提供用户数据的缓冲区,如果Winsock不能立即发送数据,这些数据将按调用的顺序排队,当可以发送时再把数据发送到网络上。用户在接受到数据已经成功发送出去的通知之前,不能破坏缓冲区中的内容
d、同步和异步
同步传输数据块与数据块之间的时间间隔是固定的,必须严格规定它们的时间关系。同步有两种传输方式:字节同步和位同步,一般采用位同步方式
异步传输是指字符之间(前一个字符结束到下一个字符开始)的时间间隔是可变的,并不需要严格地限制它们的时间关系
八、转换函数
1、字节序
一般有两种选择:从多字节数据的小段(右端,最低有效位)开始,称为小尾数;另一种是从大端(左端,最高有效位)开始顺序传输,称为大尾数
主机上面的字节序称为主机字节序
在只有一台计算机的情况下,不需要考虑字节相关的问题,计算机会自动确定用哪种方式存储数值数据。但如果把计算机连接到网络上,就必须考虑字节序问题。当两台计算机的字节序不同时,如果在传输和接收数据时都按自己的方式处理数据,就会导致错误
2、一个判断字节序的程序
在这个程序中有一个联合体,第一个成员是sval,是程序中要判断的数组,第二个成员cval与sval占用相同的内存大小,这样就可以知道sval中的高位和地位都在内存的什么位置了。这两个成员有同样的长度,当联合体中的成员长度不同时,最大的成员长度就是联合的长度
HostEndian.cpp:
#include "stdafx.h"
#include "iostream"union endian
{unsigned short sval;unsigned char cval[4];
};int _tmain(int argc, _TCHAR* argv[])
{char *info = "unknow endian";union endian t = { 0x1234 };if (t.cval[0] == 0x12 && t.cval[1] == 0x34){info = "big-endian";}else if (t.cval[0] == 0x34 && t.cval[1] == 0x12){info = "little-endian";}std::cout << "host is : " << info << std::endl;return 0;
}
3、网络字节序
为了防止字节不统一的情况发生,即通信的双方对同一数组数据做出不同的解释,而导致错误,Internet定义了存储数值数据的标准顺序----高序字节在低序字节之前,保存在内存的低地址,即大尾数字节序,也称为网络字节序,而计算机上的字节序称为主机字节序。这两个字节序有可能不一样,所以需要先进行判断
NetConvt.cpp:
#include "stdafx.h"
#include "iostream"
#include "winsock2.h"#define INADDR_INVALD 0xffffffff //无效地址static unsigned long range[] = { 0xffffffff, 0xffffff, 0xffff, 0xff };unsigned short NetHtons(unsigned short shost)
{unsigned char *p = (unsigned char *)&shost;return (unsigned short)(p[0] << 8 | p[1]);
}unsigned short NetNtohs(unsigned short snet)
{unsigned char *p = (unsigned char *)&snet;return (unsigned short)(p[0] << 8 | p[1]);
}unsigned long NetHtonl(unsigned long lhost)
{unsigned char *p = (unsigned char *)&lhost;return (unsigned long)(p[3] | (p[2] << 8) | (p[1] << 16) | (p[0] << 24));
}unsigned long NetNtohl(unsigned long lnet)
{unsigned char *p = (unsigned char *)&lnet;return (unsigned long)(p[3] | (p[2] << 8) | (p[1] << 16) | (p[0] << 24));
}/**************************************************************************** 函数功能: 把网络字节序地址转换为点分十进制的IP地址.** 参数说明: [IN] addr, 网络字节序地址.** 返 回 值: 返回点分十进制的IP地址.***************************************************************************/
char *NetNtoa(struct in_addr addr)
{static char buf[16]; //转换后的最大长度为15unsigned char *p = (unsigned char *)&addr;sprintf(buf, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);return buf;
}/**************************************************************************** 函数功能: 把点分十进制的IP地址转换为网络字节序地址.** 参数说明: [IN] cp, 点分十进制的IP地址.** 返 回 值: 成功返回网络字节序地址, 失败返回 INADDR_INVALD.***************************************************************************/
unsigned long NetAddr(const char *cp)
{unsigned char addr[4], *p = addr, c = *cp;unsigned long value;int i, n, base, digit;while (true){base = 10, value = 0; digit = 0;if (!isdigit(c)){return !INADDR_INVALD;}//1.处理前缀:0:8进制;0x:16进制;否则10进制if (c == '0'){base = 8, c = *++cp;if (c == 'x' || c == 'X'){base = 16, c = *++cp;}}//2.解析地址的一部分,处理数字,知道‘.’或非数字字符while (c = *cp++){if (isdigit(c)){if (base == 8 && c >= '8'){return INADDR_INVALD;}value = value * base + (c - '0');}else if (base == 16 && isxdigit(c)){value = (value << 4) | (c + 10 - (islower(c) ? 'a' : 'A' ));}else{break;}digit = 1; //到这说明至少有一个数字}//3.遇到‘.’的处理if (c == '.'){if (!digit || p >= addr + 3 || value > 0xff){return INADDR_INVALD;}*p++ = (unsigned char)value;c = *cp;}else{break;}}n = p - addr; //已经保存到addr中的数字个数//解析完成,看是否有数字,检查尾部字节及值的范围if (!digit || (value > range[n])|| c != '\0' && !isspace(c)){return INADDR_INVALD;}//把地址的最后一部分保存到addr中for (i = 3; i >= n; i--, value >>= 8){addr[i] = (unsigned char)(value & 0xff);}value = *(unsigned long *)addr;return value;
}int _tmain(int argc, _TCHAR* argv[])
{unsigned short host_s = 0x1234, net_s;unsigned long host_l = 0x12345678, net_l;char *addr_dec = "192.168.10.26", *p;struct in_addr addr;net_s = NetHtons(host_s);net_l = NetHtonl(host_l);std::cout << "net byte order is : net_s = 0x" << std::hex << net_s << ", net_l = 0x" << std::hex << net_l << std::endl;addr.s_addr = NetAddr(addr_dec);p = NetNtoa(addr);std::cout << "net addr is : net_s = " << addr.s_addr << ", string addr is " << p << std::endl;return 0;
}
程序不太难,比如NetNtohs、NetHtonl主要思想就是得到主机序列,在移位过来
先处理前缀部分,主要是让前面的数字乘以基数base并加上本次的数值,最后保存到addr数组中的一个过程
NetNtoa就是一个用sprintf来分割的操作;NetAddr只是一位一位的处理输入参数(点分十进制ip地址的一个过程)----首
WinSock网络编程经络----读书笔记(3)相关推荐
- 《UNIX网络编程》读书笔记——第三章 套接字编程简介
第三章 套接字编程简介 一.套接字地址结构 以socket_in命名,定义在<netinet/in.h>头文件中. struct in_addr{ in_addr_t s_addr:} ...
- JAVA编程思想读书笔记(三)--RTTI
接上篇JAVA编程思想读书笔记(二) 第十一章 运行期类型判定 No1: 对于作为程序一部分的每个类,它们都有一个Class对象.换言之,每次写一个新类时,同时也会创建一个Class对象(更恰当的说, ...
- C/C++:Winsock网络编程—ping命令的简单实现
Winsock网络编程-ping命令的简单实现 前言 先声明 博主实现的是Windows平台的ping命令的简单实现,没有做域名解析,只能直接ping ip.我们要实现ping 肯定得先知道ping的 ...
- Qt:Qt实现Winsock网络编程—TCP服务端和客户端通信(多线程)
Qt实现Winsock网络编程-TCP服务端和客户端通信(多线程) 前言 感觉Winsock网络编程的api其实和Linux下网络编程的api非常像,其实和其他编程语言的网络编程都差不太多.博主用Qt ...
- Qt:Qt实现Winsock网络编程—非阻塞模式下的简单远程控制的开发(WSAAsyncSelect)
Qt实现Winsock网络编程-非阻塞模式下的简单远程控制的开发(WSAAsyncSelect) 前言 这边博客应该是 Qt实现Winsock网络编程-TCP服务端和客户端通信(多线程) 的姐妹篇,上 ...
- 《FPGA并行编程》读书笔记专栏启动说明
<FPGA并行编程>读书笔记专栏启动说明 1. <FPGA并行编程>内容简介 2. 专栏内容简介 3. 开启专栏目的 4. 专栏内容安排 5. 专栏时间安排 6. 相关资料下载 ...
- 《亿级流量JAVA高并发与网络编程实战》笔记--------更新中
<亿级流量JAVA高并发与网络编程实战>笔记 第一章 高并发概述 "高并发技术" 是一个广义的概念,是指一种高效的地实现并发需求的解决方案,是技术领域的名称,可以包含架 ...
- WinSock网络编程基础(1)
记录学习windows网络编程过程中遇到的问题和相关笔记 基本概念: Socket: socket起源于UNIX,Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.基于&qu ...
- WinSock网络编程实用宝典(一)
一.TCP/IP 体系结构与特点 1.TCP/IP体系结构 TCP/IP协议实际上就是在物理网上的一组完整的网络协议.其中TCP是提供传输层服务,而IP则是提供网络层服务.TCP/IP包括以 ...
最新文章
- Google Protocol Buffers介绍
- snp可视化之瀑布图
- oracle的后台进程能否杀掉
- Oracle发布开源的轻量级 Java 微服务框架 Helidon 1
- C#开发XML WebService接口(SOAP)
- mysql xa 演示_mysql的XA事务恢复过程详解
- java中start与loop_java for-loop问题
- 增改删(python 版)
- [bzoj1717][Usaco2006 Dec]Milk Patterns 产奶的模式 (hash构造后缀数组,二分答案)
- 诺宝机器人编程入门教程_(完整)VEX 机器人软件编程教程
- python_字符串常用方法
- linux面试题线程与进程,​一道面试题:说说进程和线程的区别
- 国家统计局可以获取到全国5级行政区域数据
- 外贸建站教程,WordPress外贸自建站流程,会打字即可学会
- mysql角色权限关系表查询_用户、角色和权限,多表查询
- 新手网站制作教程:网站建设流程及步骤有哪些?
- yocs_velocity_smoother源码编译
- Redis存放短信验证码 RedisTemplate =>opsForValue
- 币须知道 |马云又抢占了一块高地,蚂蚁金服区块链跨境汇款正式落地,2018世界杯板块排名涨幅第一...
- 如何用A4纸排版打印并制作成四分之一大小的册子(简易说明书)
热门文章
- pkill mysql_kill、PKill、xkill 和killall----杀死进程
- Drawable介绍
- ps切图后 JAVA开发_做一个会PS切图的前端开发
- 我的英语学习计划(修订版2006.4.7)
- imap服务器怎么填写?
- 论文中的实验环境配置
- 中国古代十大感天动地诗词
- jQuery筛选方法(jQuery选择器)
- 刚出生产线上的工业路由器,为何还要做老化测试?
- 执行wsl 命令时报错 nsenter: failed to execute 564: No such file or directory