这里的“通讯”加上了引号,是因为实际上所有的socket都有通讯的功能,只是在我们的例子中,之前那个socket只负责listen,而这个socket负责接受信息并echo回去。
 我们现看看这个函数:

bool TcpServer::isAccept()
{
    unsigned int clntAddrLen = sizeof(clntAddr);

if ( (communicationSock = accept(listenSock, (sockaddr*)&clntAddr, &clntAddrLen)) < 0 ) {
        return false;
    } else {
        std::cout << "Client(IP: " << inet_ntoa(clntAddr.sin_addr) << ") connected.\n";
        return true;
    }
}

用accept()创建新的socket

在我们的例子中,communicationSock实际上是用函数accept()创建的。

int accept(int socket, struct sockaddr* clientAddress, unsigned int* addressLength);

在Linux中的实现为:

/* Await a connection on socket FD.
   When a connection arrives, open a new socket to communicate with it,
   set *ADDR (which is *ADDR_LEN bytes long) to the address of the connecting
   peer and *ADDR_LEN to the address's actual length, and return the
   new socket's descriptor, or -1 for errors.

This function is a cancellation point and therefore not marked with
   __THROW.  */
extern int accept (int __fd, __SOCKADDR_ARG __addr,
           socklen_t *__restrict __addr_len);

这个函数实际上起着构造socket作用的仅仅只有第一个参数(另外还有一个不在这个函数内表现出来的因素,后面会讨论到),后面两个指针都有副作用,在socket创建后,会将客户端sockaddr的数据以及结构体的大小传回。
        当程序调用accept()的时候,程序有可能就停下来等accept()的结果。这就是我们前一小节说到的block(阻塞)。这如同我们调用std::cin的时候系统会等待输入直到回车一样。accept()是一个有可能引起block的函数。请注意我说的是“有可能”,这是因为accept()的block与否实际上决定与第一个参数socket的属性。这个文件描述符如果是block的,accept()就block,否则就不block。默认情况下,socket的属性是“可读可写”,并且,是阻塞的。所以,我们不修改socket属性的时候,accept()是阻塞的。

accept()的另一面connect()

accept()只是在server端被动的等待,它所响应的,是client端connect()函数:

int connect(int socket, struct sockaddr* foreignAddress, unsigned int addressLength);

虽然我们这里不打算详细说明这个client端的函数,但是我们可以看出来,这个函数与之前我们介绍的bind()有几分相似,特别在Linux的实现中:

/* Open a connection on socket FD to peer at ADDR (which LEN bytes long).
   For connectionless socket types, just set the default address to send to
   and the only address from which to accept transmissions.
   Return 0 on success, -1 for errors.

This function is a cancellation point and therefore not marked with
   __THROW.  */
extern int connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len);

connect() 也使用了const的sockaddr,只不过是远程电脑上的而非bind()的本机。
        accept()在server端表面上是通过listen socket创建了新的socket,实际上,这种行为是在接受对方客户机程序中connect()函数的请求后发生的。综合起看,被创建的新socket实际上包含了listen socket的信息以及客户端connect()请求中所包含的信息——客户端的sockaddr地址。

新socket与sockaddr的关系

accept()创建的新socket(我们例子中的communicationSock,这里我们简单用newSock来带指)首先包含了listen socket的信息,所以,newSock具有本机sockaddr的信息;其次,因为它响应于client端connect()函数的请求,所以,它还包含了clinet端sockaddr的信息。
        我们说过,stream流形式的TCP协议实际上是建立起一个“可来可去”的通道。用于listen的通道,远程机的目标地址是不确定的;但是newSock却是有指定的本机地址和远程机地址,所以,这个socket,才是我们真正用于TCP“通讯”的socket。

inet_ntoa()

#include <arpa/inet.h>

/* Convert Internet number in IN to ASCII representation.  The return value
   is a pointer to an internal array containing the string.  */
extern char *inet_ntoa (struct in_addr __in) __THROW;

对于这个函数,我们可以作为一种,将IP地址,由in_addr结构转换为可读的ASCII形式的固定用法。

socket 编程入门教程(一)TCP server 端:6、创建“通讯 ”嵌套字相关推荐

  1. socket 编程入门教程(三)TCP原理:5、TCP的三次握手(three-way handshake)

    socket 编程入门教程(三)TCP原理:5.TCP的三次握手(three-way handshake) 前面3个小节介绍了socket机制对TCP协议三次握手的实现,需要强调的是,与协议独立于实现 ...

  2. socket 编程入门教程(一)TCP server 端:1、建模

    绝大部分关于socket编程的教程总是从socket的概念开始讲起的.要知道,socket的初衷是个庞大的体系,TCP/IP只是这个庞大体系下一个很小的子集,而我们真正能用上的更是这个子集中的一小部分 ...

  3. socket 编程入门教程(一)TCP server 端:7、接收与发送

    现在,我们通过accept()创建了新的socket,也就是我们类中的数据成员communicationSock,现在,我们就可以通过这个socket进行通讯了. TCP通讯模型 在介绍函数之前,我们 ...

  4. socket 编程入门教程(一)TCP server 端:5、创建监听嵌套字

    前面一小节,我们已经写出了TcpServer的构造函数.这个函数的实际作用,就是创建了listen socket(监听嵌套字).这一节,我们来具体分析这个创建的过程. socket和sockaddr的 ...

  5. socket 编程入门教程(一)TCP server 端:4、构造函数涉及的概念

    话题回到"黑社会办公室"的例子,讲概念已经扯得比较远了,不过,这一节我们还得讲概念,不过好在有些程序的例子.如果大家不想翻回去看TcpServer类的原型,我这里直接给出这个头文件 ...

  6. socket 编程入门教程(一)TCP server端:3、sockaddr与sockaddr_in

    2019独角兽企业重金招聘Python工程师标准>>> 收件人地址 一家化妆品公司将一批新产品的样品,准备发给某学校某个班的女生们免费试用.通常情况下,这件邮包的地址上可以这么写: ...

  7. socket 编程入门教程(一)TCP server 端:2、socket与文件描述符

    UNIX中的一切事物都是文件( everything in Unix is a file!) 当我在这篇教程中提到UNIX的时候,其意思专指符合UNIX标准的所谓"正统"UNIX的 ...

  8. socket 编程入门教程(一)TCP server 端:3、sockaddr与sockaddr_in

    收件人地址 一家化妆品公司将一批新产品的样品,准备发给某学校某个班的女生们免费试用.通常情况下,这件邮包的地址上可以这么写: 收件人:全体女生. 地址:A省B市C学校,X级Y班. 但是,如果在描述地址 ...

  9. socket 编程入门教程(三)TCP原理:7、TCP连接的关闭

    2019独角兽企业重金招聘Python工程师标准>>> TCP连接一旦建立,服务器端和客户端就成为了对等关系,任何一方都可以发出关闭握手请求,甚至可以同时发出关闭握手请求.TCP的连 ...

最新文章

  1. Ubutun重启网卡
  2. indexof方法_[ 翻译 ] ES6中数组去重的三种方法
  3. value proposition canvas
  4. 牛客网【每日一题】3月27日 数学考试
  5. 网络无人值守安装linux----kickstart
  6. 不通过ios审核 安装苹果app php,iOS APP审核被拒的解决之道(2.1)
  7. pyintaller exe 后 print的内容 怎么体现_使用Github Actions自动化构建exe
  8. (二)元学习算法MAML简介及代码分析
  9. Jquery_artDialog对话框弹出
  10. A1075[PAT JUDGE] 好题
  11. c语言课程设计参考,c语言课程设计参考
  12. element-ui的upload 上传组件 照片墙当超过限定图片后隐藏上传按钮
  13. 教你如何写出完美的论文——5. 做笔记
  14. 【飞轮储能】基于matlab simulink飞轮储能(永磁同步电机)仿真【含Matlab源码 2421期】
  15. idea @Autowired 飘红
  16. iphone计算机历史信息,“领先业界5年!” 苹果iPhone历史回顾
  17. C 语言printf打印各种数据类型的方法(u8/s8/u16/s16.../u64/double/float)(全)
  18. 【LaTex的PPT模板集】- (亲测有效)在线PPT模板及其使用方法,overleaf与TeXstudio支持中文方法
  19. 大数据——Spark GraphX中算法介绍
  20. C# 获取本地输入法列表,切换中英文输入法

热门文章

  1. windows彻底删除php,windows如何删除php
  2. 广西2021普通高考成绩查询,2021广西高考成绩什么时候出
  3. 移植wpa_supplicant软件与DHCP软件解密WPA/WPA2 加密的无线网络
  4. phantomJs原理
  5. LeetCode:204. 计数质数
  6. mac os x10.9.2 查看进程对应端口
  7. iOS 直接使用16进制颜色
  8. Xamarin Mono for VS开发窗体标题(Title)乱码解决方案
  9. CTabCtrl控件标签的相关设置
  10. 坑爹的UICollectionView