一、创建socket

/*  创建一个socket  */
int socket(int family, int type, int protocol); /* 参数说明 */
// domain:使用哪个底层协议族
// type:指定服务类型
// protocol:使用哪个协议

1. type参数指定的服务类型有SOCK_STREAM服务(流服务)和SOCK_DGRAM服务(数据报服务)

  • 对TCP/IP协议族而言,其值取SOCK_STREAM表示传输层使用TCP协议,取SOCK_DGRAM表示传输层使用UDP协议。

补:type参数可以接受上述服务类型与下面两个重要的标志相与的值:SOCK_NONBLOCK和SOCK_CLOEXEC。它们分别表示将新创建的socket设为非阻塞的,以及用fork调用创建子进程时在子进程中关闭该socket。

2. protocol参数一般都设置为0,表示使用默认协议

  • 因为它是在前两个参数构成的协议集合下,再选择一个具体的协议。而前两个参数已经完全决定了它的值。

在UNIX/Linux下,所有东西都是文件,socket也不例外,它就是可读、可写、可控制、可关闭的文件描述符。

二、给socket命名——将socket与socket地址绑定

/* 将一个socket与socket地址绑定 */
int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen); /* 参数说明 */
// myaddr:其所指的socket地址分配给未命名的sockfd文件描述符
// addrlen:指出该socket地址的长度

1. 服务器程序需要命名socket,这样客户端才能知道该如何连接它;而客户端通常不需要命名socket,而是采用匿名方式(即使用操作系统自动分配的socket地址)

2. 两种常见的errno是EACCES和EADDRINUSE

  • EACCES:被绑定的地址是受保护的地址,仅超级用户能访问。如普通用户将socket绑定到知名服务端口(端口号为0~1023)上时,bind将返回EACCES错误。
  • EADDRINUSE:被绑定的地址正在使用中。如将socket绑定到一个处于TIME_WAIT状态的socket地址。

三、监听socket——将一个主动socket转换成被动socket,使服务器可以接受客户连接

/* 创建一个监听队列以存放待处理的客户连接 */
int listen(int sockfd, int backlog); /* 参数说明 */
// backlog:指定内核监听队列的最大长度

1. backlog参数表示处于完全连接状态(ESTABLISHED)的socket的上限

补:在内核版本2.2之前的Linux中,backlog参数是指所有处于半连接状态(SYN_RCVD)和完全连接状态(ESTABLISHED)的socket上限。

2. 当监听队列的长度超过backlog时,服务器将不再受理新的客户连接,客户端也将收到ECONNREFUSED错误信息。

四、接受连接

/* 从监听队列中接受一个连接 */
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); /* 参数说明 */
// addr:指向被接受连接的远端socket地址
// addrlen:远端socket地址的长度

1. 取出已完成连接(ESTABLISH)队列的队首连接,如果该队列为空,那么进程将被投入睡眠(假设socket为默认的阻塞方式)

补:accept只是从监听队列中取出连接,而不论连接处于何种状态,如该队首连接对应的客户端掉线或提前退出。

2. accept返回一个新的连接socket,该socket唯一地标识了这个被接受的连接

  • 服务器通过读写该socket来与被接受连接对应的客户端通信。

五、发起连接——客户端主动与服务器建立连接

/* 主动与服务器建立连接 */
int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen); /* 参数说明 */
// servaddr:指向接受连接的远端socket地址
// addrlen:远端socket地址的长度

1. sockfd唯一地标识这个发起的连接

2. 两种常见的errno是ECONNREFUSED和ETIMEDOUT

  • ECONNREFUSED:目标端口不存在,连接被拒绝。
  • ETIMEDOUT:连接超时。

3. 若connect失败,则该socket不再可用,必须关闭  

六、关闭连接——关闭连接对应的socket

/*  关闭文件描述符  */
int close(int fd); /* 立即终止连接 */
int shutdown(int sockfd, int howto); /* 参数说明 */
// howto:决定了shutdown的行为,可选值为SHUT_RD、SHUT_WR和SHUT_RDWR

1. close将fd的引用计数减1,故其并非总能立即关闭一个连接

2. shutdown能够分别关闭socket上的读或写,或者都关闭

七、余音绕梁

1. 客户往往不给socket命名,而是采用匿名形式,那么是如何确定socket地址的呢?

当调用connect时,内核将根据所用外出网络接口来确定IP地址,并选择一个临时端口作为源端口。

2. socket被创建后,其往往被假设为一个主动socket,即认为它将发起连接。而服务器往往调用listen使其变为被动socket,使得内核创建监听队列,从而可以接受连接。  

3. 系统调用与连接队列

  • connect调用将激发TCP的三路握手过程。
  • 当来自客户的SYN到达时,TCP在其半完成连接队列中创建一个新条目,该条目一直保留到三路握手的第三个分节到达或者该条目超时。
  • 如果三路握手正常完成,该条目就从半完成连接队列转移到完全连接队列的队尾。
  • 当服务器进程调用accept时,完全连接队列的队头将返回给进程。

  

  

  

  

  

  

4. 基本socket函数的更多相关文章

  1. 使用socket()函数创建套接字

    在Linux中,一切都是文件,除了文本文件.源文件.二进制文件等,一个硬件设备也可以被映射为一个虚拟的文件,称为设备文件.例如,stdin 称为标准输入文件,它对应的硬件设备一般是键盘,stdout ...

  2. PHP Socket实现websocket(二)Socket函数

    PHP socket函数是调用系统的的Socket函数,可以参考C语言的socket函数. Socket函数:http://php.net/manual/en/book.sockets.php 服务器 ...

  3. Windows套接字Socket函数

    1.使用套接字函数之前,先要加载套接字函数库: #include "Winsock2.h" #pragma comment(lib,"Ws2_32.lib") ...

  4. socket函数

    为了执行网络IO,一个进程必须做的第一件事就是调用socket函数,指定期望的通信协议类型 int socket(int family,int type,int protocol); 其中,famil ...

  5. OVERLAPPED相关的socket函数介绍

    OVERLAPPED相关的socket函数介绍 上一篇文章介绍了<Windows核心编程>OVERLAPPED结构与内核对象IOCompletionPort相关概念,见http://www ...

  6. windows socket函数详解

    windows socket函数详解 近期一直用第三方库写网络编程,反倒是遗忘了网络编程最底层的知识.因而产生了整理Winsock函数库的想法.以下知识点均来源于MSDN,本人只做翻译工作.虽然很多前 ...

  7. python socket 函数介绍

    socket 函数原型:socket.socket([family[,type[,proto]]]) family参数取值(协议族): socket.AF_INET        -->ipv4 ...

  8. 【读书笔记】socket函数

    socket函数 简介 应用程序调用socket函数来创建一个能够进行网络通信的套接字. 1 2 3 4 5 /* 头文件 */ #include <sys/types.h> #inclu ...

  9. socket()函数介绍

    socket()函数介绍 socket函数介绍 函数原型 domain type protocol errno 示例 函数原型 socket()函数的原型如下,这个函数建立一个协议族为domain.协 ...

  10. php socket 函数

    创建基于socket的应用程序,就需要详细了解socket的操作方法,这里列举PHP中一些重要的socket函数.   1. socket_create ( int $domain , int $ty ...

随机推荐

  1. BZOJ 4520: [Cqoi2016]K远点对(k-d tree)

    Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 1162  Solved: 618[Submit][Status][Discuss] Descripti ...

  2. CentOS 7紧急救援模式修改root用户密码的方法

    最近无聊在网上搜索linux系统root用户密码破解方法,看来很多朋友的博文,同时也试了一下,但是感觉他们写的还是不是很清晰.简洁,因此自己就心血来潮写了这篇博文,提供一个比较清晰的思路给新手,如果有 ...

  3. js节点操作实例

    写了一个简单的小例子来引用js实例 1. 初步节点操作: 2.兼容性节点操作: 3.节点的类型,名字: 4.使用setAttribute设置属性 5.节点复制操作: 6.删除和替换节点 如有错误,还望 ...

  4. 高性能MySQL--MySQL数据类型介绍和最优数据类型选择

    MySQL支持的数据类型很多,那么选择合适的数据类型对于获得高性能就至关重要.那么就先了解各种类型的优缺点! 一.类型介绍 1.整型类型 整型类型有: TINYINT,SMALLINT,MEDIUMI ...

  5. tp5 的nginx配置

    下面简单说明一下tp5运行在nginx上的配置. 原文地址:小时刻个人博客>http://small.aiweimeng.top/index.php/archives/tp5_nginx.htm ...

  6. Linux中的阻塞机制

    我们知道在字符设备驱动中,应用层调用read.write等系统调用终会调到驱动中对应的接口. 可以当应用层调用read要去读硬件的数据时,硬件的数据未准备好,那我们该怎么做? 一种办法是直接返回并报错 ...

  7. 《你不知道的JavaScript》系列分享专栏

    <你不知道的JavaScript>系列分享专栏 你不知道的JavaScript”系列就是要让不求甚解的JavaScript开发者迎难而上,深入语言内部,弄清楚JavaScript每一个零部 ...

  8. 与Linux的第一次遭遇

    我的与linux首次遭遇战 虚拟机安装 安装虚拟机我遇到的问题个数可以缩减到1--我几乎没遇到安装虚拟机的问题!我严格按照老师给的链接去下载那个VirtualBox,尽管那个网页是全英文的,但是我像看 ...

  9. 20155302 《Java程序设计》实验一(Java开发环境的熟悉)实验报告

    20155302 <Java程序设计>实验一(Java开发环境的熟悉)实验报告 实验内容 1.使用JDK编译.运行简单的Java程序: 2.使用Eclipse 编辑.编译.运行.调试Jav ...

  10. 20155325《Java程序设计》实验一(Java开发环境的熟悉)实验报告

    实验一Java开发环境的熟悉-1 提交 Linux或Window或macOS中命令行下运行Java的截图 运行结果包含自己学号等证明自己身份的信息 实验一Java开发环境的熟悉-2 提交 Linux或 ...