【网络基础编程】第三节 C/S
前面介绍的程序,不管Service 端还是 Client端,都有一个问题,就是处理完一个 accept 请求立即退出,没有太大的实际意义。能不能像Web 服务器那样一直接收Client 端的请求呢?能,使用 While 循环即可。
修改前面的代码,是我们的服务端可以不断响应 Client 端的请求。
升级版Socket Demo
1. socket缓冲区
在迭代服务端和客户端的核心,就是如何使用write() 和 read() 函数,接下来介绍数据是如何传递的。
write()
函数并不立即向网络中传输 Data,而是先将 Data 写入缓冲区中,再由 TCP 协议将数据从缓冲区发送到目标机器。一旦将 Data 写入缓冲区,函数就可以成功返回,不管 Data 有没有到达目标机器,也不管他们何时被发送到网络,这些都是 TCP 协议负责的事情。
TCP 协议独立于 write() 函数,Data 有可能刚被写入缓冲区就发送到网络,也可能在缓冲区中不断积压,多次写入的数据被一次性发送到网络,这要取决于网络情况、当前线程是否空闲等诸多因素,不由程序员控制。
read()
函数也是如此,也从输入缓冲区中读取 Data,而不是直接从网络读取。
这些I/O 缓冲区特性可整理如下:
- I/O 缓冲区在每个 TCP 套接字中单独存在;
- I/O 缓冲区在创建套接字时自动生成;
- 即使关闭套接字也会继续传送
输出缓冲区
中遗留的 Data; - 但是关闭套接字也将丢失
输入缓冲区
中的 Data。
输入/输出 缓冲区的默认大小可以通过getsockopt() 函数获取:
unsigned optVal;
socklen_t optLen = sizeof(int);
getsockopt(serv_socket, SOL_SOCKET, SO_SNDBUF, (char*)&optVal, &optLen);
printf("Buffer length: %d\n", optVal);
// 结果:2^17
Buffer length: 131072
2. 阻塞模式
对于 TCP 套接字(默认情况下)。
当使用write() 函数发送数据时:####
- 首先会检查输出缓冲区,如果缓冲区的可用长度小于要发送的数据,那么write() 会阻塞(暂停执行),直到输出缓冲区中的 Data 被发送到目标机器,腾出足够的空间,才唤醒 write() 函数继续写入 Data。
- 如果 TCP 协议正在向网络发送 Data,那么输出缓冲区会被锁定,不允许吸入,write() 也会被阻塞(暂停执行),知道数据发送完毕输出缓冲区解锁,才唤醒write() 函数继续写入 Data。
- 如果要写入的 Data 大于缓冲区的最大长度,那么 Data 将分批写入。
- 知道所有的数据被写入输出缓冲区, write() 才能返回。
当使用read() 函数读取数据时:####
- 首先会检查输入缓冲区,如果缓冲区中有数据,那么就会读取,否则函数会被阻塞,知道网络上数据来到。
- 如果要读取的数据长度小于缓冲区的数据长度,那么就不能一次性将缓冲区中的数据独处,剩余数据将不断积压,直到read() 函数再次读取。
- 直到读取完数据之后,read() 函数才会返回,否则一直被阻塞。
阻塞模式总结
以上就是TCP 套接字的阻塞模式。所谓阻塞,也就是上一步动作没有完成,下一步动作将被暂停,直到上一步动作完成之后才能继续,以保持同步性。
3. 使用域名获取IP 地址
包含: #include<netdb.h>
首先介绍netdb.h
中的网络数据库返回的结构:#####
struct hostent {
char *h_name; /* official name of host */
char **h_aliases; /* alias list */
int h_addrtype; /* host address type */
int h_length; /* length of address */
char **h_addr_list; /* list of addresses from name server */
#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
#define h_addr h_addr_list[0] /* address, for backward compatibility */
#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */
};
- h_name :官方域名。
- h_aliases :别名,多个域名访问同一个主机。同一个IP地址可以绑定多个域名,因此除了当前域名还可以指定其他域名。
- h_addrtype :gethostbyname() 不仅仅支持IPv4,还可以支持IPv6,可以通过此成员获取IP 地址族信息。
- h_lenght :保存IP 地址的长度,IPv4长度为4 个字节,IPv6长度为16 个字节。
- h_addr_list :
重要成员
。通过该成员以整数形式保存域名对应的IP 地址。对于用户较多的服务器,可能会分配多个IP 地址给同一个域名,利用多个服务器进行均衡负载。
struct hostent 结构体变量的组成如下图所示:####
测试代码:####
假设获取本机的IP 地址。步骤:1.通过gethostname()获取本机的域名;2.通过gethostbyname() 获取域名的IP 数据库信息。
(因为在iOS8.0以上真机测试,通过gethostbyname() 无法解析域名来获取IP 信息了,推荐使用getifaddrst来获取IP地址)###
struct hostent * struct_hLib; // 储存IP信息的结构体
char ** p_h_addr_list; // 获取IP信息中IP列表
char str[32]; // 获取IP列表中具体的IP地址
char hostname[32]; // 储存域名
gethostname(hostname, sizeof(hostname)); // 获取本地域名,存储到hostname
struct_hLib = gethostbyname(hostname); // 获取指定域名的IP信息,存储到struct_hLib
p_h_addr_list = struct_hLib->h_addr_list; // 通过struck_hLib 获取IP列表
for (; *p_h_addr_list!=NULL; p_h_addr_list++)
{
//*> 打印具体的IP地址
printf("address: %s\n",inet_ntop(struct_hLib->h_addrtype, *p_h_addr_list, str, sizeof(str)));
}
打印结果:
address: 192.168.1.3
讲解一下inet_ntop
、gethostname
、gethostbyname
的用法:
1.inet_ntop:####
const char * inet_ntop(int af, const void *restrict src, char *restrict dst, socklen_t size);
官方文档解释:
The function inet_ntop() converts an address *src from network format
(usually a struct in_addr or some other binary form, in network byte
order) to presentation format (suitable for external display purposes).
The size argument specifies the size, in bytes, of the buffer *dst. It
returns NULL if a system error occurs (in which case, errno will have
been set), or it returns a pointer to the destination string. This func-tion function
tion is presently valid for AF_INET and AF_INET6.
- af : Address Family。
- src : 来自于网络地址格式,例如*p_h_addr_list 这种二进制形式的地址。
- dst :存放转化后的字符串指针。
- size : 返回字节的大小。
返回把网络地址转换成本地地址。
2.gethostname####
int gethostname(char * destinnationStr, size_t);
- destinnationStr :存放本地域名的字符串指针。
- size_t : 存放本地地址的长度。
返回当前本地域名
3.gethostbyname
struct hostent *gethostbyname(const char *);
【网络基础编程】第三节 C/S的更多相关文章
- Linux应用程序设计之网络基础编程
1.TCP/IP协议概述 1.1.OSI参考模型及TCP/IP参考模型 OSI协议参考模型是基于国际标准化组织(ISO)的建议发展起来的,从上到下工分为7层:应用层,表示层,会话层,传输层,网络层,数 ...
- 网络基础编程_5.4聊天室-IOCP服务器
聊天室-IOCP服务器 main 创建完成端口内核对象(CreateIoCompletionPort) 获取核心数并创建线程(GetSystemInfo + CreateThread) 创建套接字并绑 ...
- JAVA基础知识之网络编程——-网络基础(Java的http get和post请求,多线程下载)
本文主要介绍java.net下为网络编程提供的一些基础包,InetAddress代表一个IP协议对象,可以用来获取IP地址,Host name之类的信息.URL和URLConnect可以用来访问web ...
- Java 网络编程(一) 网络基础知识
链接地址:http://www.cnblogs.com/mengdd/archive/2013/03/09/2951826.html 网络基础知识 网络编程的目的:直接或间接地通过网络协议与其他计算机 ...
- Python3 与 C# 网络编程之~ 网络基础篇
最新版本查看:https://www.cnblogs.com/dotnetcrazy/p/9919202.html 入门篇 官方文档:https://docs.python.org/3/library ...
- 网络编程—网络基础概览、socket,TCP/UDP协议
网络基础概览 socket概览 socket模块—TCP/UDP的实现 TCP/UDP总结 网络基础概览 osi七层协议各层主要的协议 # 物理层传输电信号1010101010 # 数据链路层,以太网 ...
- 网络编程基础:网络基础之网络协议、socket模块
操作系统(简称OS)基础: 应用软件不能直接操作硬件,能直接操作硬件的只有操作系统:所以,应用软件可以通过操作系统来间接操作硬件 网络基础之网络协议: 网络通讯原理: 连接两台计算机之间的Intern ...
- python基础(29):网络编程(软件开发架构、网络基础、套接字初使用)
1. 软件开发架构 我们了解的程序之间通讯的应用可分为两种: 第一种是应用类:qq.微信.百度网盘.腾讯视频这一类是属于需要安装的桌面应用. 第二种是web类:比如百度.知乎.博客园等使用浏览器访问就 ...
- Java Socket编程----网络基础
详见:https://www.cnblogs.com/rocomp/p/4790340.html Java最初是作为网络编程语言出现的,其对网络提供了高度的支持,使得客户端和服务器的沟通变成了现实,而 ...
随机推荐
- Android:使用代理服务器安装SDKs
在使用Android SDK Manager来安装SDK时,因为google的ip被墙了,所以下载文件时,下载不到. 面对不能访问google的问题,通常有下列方案: 1)修改hosts文件,需要有正 ...
- x01.Weiqi.7: 调整重绘
GitHub 谁方便谁拍,谁重要拍谁.在这个砖头满天飞的时代,一个好的生态显得尤为重要. 红颜小头发,要的很简单. 也许成绝唱,只因鱼断肠. 姚贝福娃的离去,除感叹人生无常外,活着做点有意义的事情, ...
- WPF 依赖属性
依赖属性,简单的说,在WPF控件应用过程中,界面上直接可以引用的属性 如:<Button Content="aaa"></Button> Content称为 ...
- android Bundle savedInstanceState用途
经常会出现用户按到home键,退出了界面,或者安卓系统意外回收了应用的进程,这种情况下,使用Bundle savedInstanceState就可以用户再次打开应用的时候恢复的原来的状态 (以下转自: ...
- php 三种数组
在 PHP 中,有三种数组类型: 索引数组 - 带有数字索引的数组 关联数组 - 带有指定键的数组 多维数组 - 包含一个或多个数组的数组 获得数组的长度 - count() 函数
- [Django]模型学习记录篇--基础
模型学习记录篇,仅仅自己学习时做的记录!!! 实现模型变更的三个步骤: 修改你的模型(在models.py文件中). 运行python manage.py makemigrations ,为这些修改创 ...
- Java基础知识笔记(三:文件与数据流)
一.输入流与输出流 输入流将数据从文件.标准输入或其他外部输入设备中加载到内存.输出流的作用则刚好相反,即将在内存中的数据保存到文件中,或传输给输出设备.输入流在Java语言中对应于抽象类java.i ...
- HTTP状态码302、303和307的故事
今日读书,无法理解HTTP302.303.307状态码的来龙去脉,决定对其做深究并总结于本文. <HTTP权威指南>第3章在讲解30X状态码时,完全没有讲清楚为什么要有 ...
- HashMap实现原理及源码分析
哈希表(hash table)也叫散列表,是一种非常重要的数据结构,应用场景及其丰富,许多缓存技术(比如memcached)的核心其实就是在内存中维护一张大的哈希表,而HashMap的实现原理也常常出 ...
- Html文档流和文档对象模型DOM理解
前言 在理解浮动和定位时,触碰到文档流概念.为了更好理解浮动和定位,学习了文档流和DOM(文档对象模型). 正文 DOM(文档对象模型)简单理解就是编写的html页面所有内容构成的树形结构.例如: 根 ...