一、socket 函数

#include <sys/socket.h>
  int socket (int family, int type, int protocol);
      Returns: non-negative descriptor if OK, - on error
  • family参数指明协议族(协议域)。它们分别是:   AF_INET——IPv4 协议、 AF_INET6——IPv6协议 、 AF_LOCAL(AF_UNIX)——Unix域协议 、AF_ROUTE——路由套接口协议、AF_KEY——密钥套接口协议
  •  type指明套接口类型。它们分别是:  SOCK_STREAM——字节流套接口、SOCK_DGRAM——数据报套接口、SOCK_SEQACKET——有序分组套接口、SOCK_RAW——原始套接口
  • protocol指明某个协议类型常值,或者也可以设置为0,以选择所给定family和type组合的系统缺省值。它们分别是:IPPROTO_TCP——TCP传输协议、IPPROTO_UDP——UDP传输协议、IPPROTO_STCP——STCP传输协议

family和type参数的组合如下:

  

 socket成功时会返回一个小的非负整数值,它与文件描述字一致,我们成为套接字(socket descriptor)。AF_前缀表示地址族,PF_前缀表示协议族。不过这两个东西是相等的,所以用哪个都行。


二、connect函数

  connect函数用于 TCP客户端与TCP服务端建立连接

 #include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);
             Returns: if OK, - on error
  • sockfd是套接字。
  • servaddr是指向套接字地址结构的指针
  • adrlen是套接字地址结构的大小
  • socket address structrue(套接字地址)必须含有IP地址和端口号

  client在调用connect之前不必非得调用bind函数,因为如果需要的话,内核会确定源IP地址,并选择一个临时端口作为源端口。调用conect函数将initiates TCP的三路握手过程。

出错返回有以下情况:

  • 如果client TCP没有收到SYN segment的响应,那么ETIMEDOUT将返回。
  • 如果服务器TCP对client的响应是RST,这说明服务器在我们指定的端口上并没有进程在等待和它连接,这是一个hard error,当客户收到RST后,就返回ECONNREFUSED
  • 若客户发出的SYN在中间的某个路由器上引发了"destination unreachable”错误,则继续发送SYN信号,如果在某个规定时间内,仍未收到响应,则把保存的消息作为EHOSTUNREACH或者ENETUNREACH错误返回。

如果connect失败,这个socket就不能用了,必须关闭。我们不能用这样的套接口再次调用connect函数。

 


三、bind函数 

  bind函数指定一个本地协议地址分配给一个未命名的socket。使用Socket函数创建的那些套接字初始化是没有命名的,它们只有通过地址族才能被识别到,对于网络协议:协议地址是32位的IPv4地址或128位的IPv6地址与16位的TCP或UDP的端口号的组合。调用bind函数,可以指定一个端口号、一个IP地址、也可以两者都指定、也可以都不指定。

#include <sys/socket.h>
  int bind (int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);
            Returns: if OK,- on error
  • sockfd是套接字
  • myaddr是指向特定协议地址结构的指针
  • addrlen是该地址结构的长度
  • 如果一个TCP client或者server 没有绑定端口,kernel在调用connect或listen时,就会选择一个临时端口。内核选择临时端口,对于TCP客户来说是正常的
  • 一个process可以bind特定的IP地址到它的socket,这个IP地址一定属于其所在主机的网络接口之一。对于TCP,这就为该socket发送的IP数据报指定了源IP地址;对于TCP服务器,这就限定了该套接口只接收那些目的地为这个IP地址的客户连接。
  • 如果TCP没有把IP地址绑定到它的套接口上,内核就会把客户发送的SYN的宿IP地址作为服务器的源IP地址。

四、listen函数

  TCP服务器调用listen函数,主要有两个作用:

  • 当socket函数创建一个socket时,它被指定为active socket(主动套接口),也就是说它是一个将会调用connect发起连接的客户套接口。listen函数将未连接的套接口转换为一个passive socket(被动套接口),指示内核接受指向socket 的到来的连接请求。调用TCP将sockets的状态从CLOSED转换为LISTEN状态
  • 第二个参数指定了内核应该为这个socket排队的最大连接数。
#include <sys/socket.h>
#int listen (int sockfd, int backlog);
      Returns: if OK, - on error

  这个函数应该在调用socket和bind函数之后,在调用accept函数之前。

 内核为每个给定的监听套接口维护两个队列:

  • 未完成连接队列(incomplete connection queue ):每个这样的SYN分节对应其中一项,已知由某个服务器发出并到达服务器,而服务器正在等待完成相应的TCP三路握手过程。这些套接口处于TCP_RCVD状态。
  • 已完成连接状态(completed comnection queue): 每个已完成TCP三路握手过程的客户对应其中一项,这些套接口处于ESTABLISHED状态。

  • 当来自client的SYN到达时,TCP在未完成连接队列中创建一个新项,然后响应以三路握手的第二个分节(服务器的SYN响应,其中捎带对客户SYN的ACK)。这一项一直保留在未完成队列,直到三路握手的第三个分节(客户对服务器SYN的ACK)达到或者该项超时。
  • 如果三路握手正常,该项就从未完成队列移动到已完成队列的对尾。
  • 当进程调用accept时,已完成队列中的队头项将返回给进程,或者如果该队列为空,那么进程将被投入睡眠,直到TCP在该队列中放入一项才唤醒它。
  • 在三路握手正常完成的前提下,未完成连接队列中的任何一项在其中存留的时间就是一个RTT(客户到服务器的往返时间)

 五、accept函数

  TCP 服务器调用accept函数,从一个已完成队列的队头(complete connection queue)返回一个已完成的连接。如果已完成连接队列为空,那么进程被投入睡眠

  

#include <sys/socket.h>
  int accept (int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);
    Returns: non-negative descriptor if OK, - on error
  • cliaddr:返回已连接对端进程(client)协议地址
  • addrlen:value-result(值-结果参数),调用前是*cliaddr所指的套接口地址的长度;返回时,其整数值为内核存在该套接口地址结构内的确切字节数。

如果accept成功,那么其返回值是由内核自动升成的一个全新描述字,代表与client的TCP连接。我们称这个函数的第一个参数是listening socket(监听套接口),函数返回的是connected socket(已连接套接口)

服务器在仅仅只创建一个listening socket,它存在于服务器的整个生命周期内。内核为每个服务器进程已接受的客户创建一个已连接套接口。当服务器完成对于某个给定客户的服务时,相应的已连接套接口的服务就被关闭。  

  本函数最多返回三个值:

  • 一个既可能是新套接口描述字也可能是出错提示整数的整数,客户进程的协议地址(由cliaddr所指)以及该地址的大小(由addrlen指针所指),如果对客户协议地址不感兴趣,可以把cliaddr和addrlen均置为空指针。

六、并发服务器 

  

 

基本TCP Sockets编程的更多相关文章

  1. linux tcp/ip编程和windows tcp/ip编程差别以及windows socket编程详解

    最近要涉及对接现有应用visual c++开发的tcp客户端,花时间了解了下windows下tcp开发和linux的差别,从开发的角度而言,最大的差别是头文件(早期为了推广尽可能兼容,后面越来越扩展, ...

  2. 异常处理、socke基于TCP协议编程

    一.异常处理 1.错误和异常 1.程序中难免出现错误,而错误分成两种 (1)语法错误(这种错误过不了Python解释器的语法检测,必须在程序执行前改正) #语法错误示范一 if #语法错误示范二 de ...

  3. C# TCP应用编程三 异步TCP应用编程

    利用TcpListener和TcpClient类在同步方式下接收.发送数据以及监听客户端连接时,在操作没有完成之前一直处于阻塞状态,这对于接受.发送数据量不大的情况或者操作勇士较短的情况下是比较方便的 ...

  4. C# TCP应用编程二 同步TCP应用编程

    不论是多么复杂的TCP 应用程序,双方通信的最基本前提就是客户端要先和服务器端进行TCP 连接,然后才可以在此基础上相互收发数据.由于服务器需要对多个客户端同时服务,因此程序相对复杂一些.在服务器端, ...

  5. Linux下TCP网络编程与基于Windows下C#socket编程间通信

    一.linux下TCP网络编程基础,需要了解相关函数 Socket():用于套接字初始化. Bind():将 socket 与本机上的一个端口绑定,就可以在该端口监听服务请求. Listen():使s ...

  6. JAVA TCP网络编程学习笔记

    一.JAVA网络编程概述 网络应用程序,就是在已实现网络互联的不同计算机上运行的应用程序,这些程序之间可以相互交换数据.JAVA是优秀的网络编程语言,Java网络编程的类库位于java.net包中.J ...

  7. 一种C# TCP异步编程中遇到的问题

    最近在维护公司的一个socket服务端工具,该工具主要是提供两个socket server服务,对两端连接的程序进行数据的透明转发. 程序运行期间,遇到一个问题,程序的一端是GPRS设备,众所周知,G ...

  8. 简述TCP网络编程本质

    基于事件的非阻塞网络编程是编写高性能并发网络服务程序的主流模式,头一次使用这种模式编程需要转换思维模式 .把原来的"主动调用recv()来接收数据,主动调用accept()来接受连接,主动调 ...

  9. tcp 网络编程

    网络编程同时也是进程间的一种通信:服务器进程和应用进程间的通信. OSI:开放式系统互联 OSI 7层模型:                                               ...

随机推荐

  1. HttpClient 之Fluent API 简单使用

    相比于HttpClient 之前的版本,HttpClient 4.2 提供了一组基于流接口(fluent interface)概念的更易使用的API,即Fluent API. 为了方便使用,Fluen ...

  2. android中的SQLite数据库

    SQLite是android中集成的一个轻量级的数据库,该数据库支持绝大部分SQL92语法 SQLiteDatabase代表一个数据库(底层就是一个数据库文件),一旦应用程序获得了代表指定数据库的SQ ...

  3. SpringData 完全入门指南

    SpringData 笔记 1. 配置项目 1.pom.xml <?xml version="1.0" encoding="UTF-8"?> < ...

  4. 自定义vant ui steps组件效果实现

    记录个问题,当作笔记吧:因为vue项目的移动端vant ui 的step组件跟ui设计图有差别,研究了半天还是没法使用step组件,只能手动设置一个 先上效果图和代码: (1)HTML部分 <d ...

  5. 2018-8-29-Roslyn-静态分析

    title author date CreateTime categories Roslyn 静态分析 lindexi 2018-08-29 09:10:19 +0800 2018-03-13 14: ...

  6. 嵌入式平台 RAM与ROM区分

    ROM(Read Only Memory)和RAM(Random Access Memory)指的都是半导体存储器,ROM在系统停止供电的时候仍然可以保持数据,而RAM通常是在掉电之后就丢失数据,典型 ...

  7. Linux 任务管理器(二)

    特殊文件与进程 fuser命令 [root@localhost home]# fuser -muv . 用户 进程号 权限 命令 /home: root kernel mount (root)/hom ...

  8. 批量修改root密码

    公司有五十多台服务器.每台服务器中使用的密码完全不同,同时操作系统也不一样,centos5,6,7 .ubuntu,windows都有,更不用提其中各种小版本. root密码定期更改是一个大问题(wi ...

  9. linux,进行批量下载文件操作

     wget -i url.txt -P ./Photo 批量下载图片(一般是某个相册的图片) 首先先得到一张图片的地址如:www.example.com/pic/001.jpg 同相册的图片地址会有一 ...

  10. Java 基础 - 单行初始化数组 Initialize array in one line

    Code: public class ClassName { private char[] value = new char[]{'a','b'}; private char[] value2 = { ...