基本TCP Sockets编程
一、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编程的更多相关文章
- linux tcp/ip编程和windows tcp/ip编程差别以及windows socket编程详解
最近要涉及对接现有应用visual c++开发的tcp客户端,花时间了解了下windows下tcp开发和linux的差别,从开发的角度而言,最大的差别是头文件(早期为了推广尽可能兼容,后面越来越扩展, ...
- 异常处理、socke基于TCP协议编程
一.异常处理 1.错误和异常 1.程序中难免出现错误,而错误分成两种 (1)语法错误(这种错误过不了Python解释器的语法检测,必须在程序执行前改正) #语法错误示范一 if #语法错误示范二 de ...
- C# TCP应用编程三 异步TCP应用编程
利用TcpListener和TcpClient类在同步方式下接收.发送数据以及监听客户端连接时,在操作没有完成之前一直处于阻塞状态,这对于接受.发送数据量不大的情况或者操作勇士较短的情况下是比较方便的 ...
- C# TCP应用编程二 同步TCP应用编程
不论是多么复杂的TCP 应用程序,双方通信的最基本前提就是客户端要先和服务器端进行TCP 连接,然后才可以在此基础上相互收发数据.由于服务器需要对多个客户端同时服务,因此程序相对复杂一些.在服务器端, ...
- Linux下TCP网络编程与基于Windows下C#socket编程间通信
一.linux下TCP网络编程基础,需要了解相关函数 Socket():用于套接字初始化. Bind():将 socket 与本机上的一个端口绑定,就可以在该端口监听服务请求. Listen():使s ...
- JAVA TCP网络编程学习笔记
一.JAVA网络编程概述 网络应用程序,就是在已实现网络互联的不同计算机上运行的应用程序,这些程序之间可以相互交换数据.JAVA是优秀的网络编程语言,Java网络编程的类库位于java.net包中.J ...
- 一种C# TCP异步编程中遇到的问题
最近在维护公司的一个socket服务端工具,该工具主要是提供两个socket server服务,对两端连接的程序进行数据的透明转发. 程序运行期间,遇到一个问题,程序的一端是GPRS设备,众所周知,G ...
- 简述TCP网络编程本质
基于事件的非阻塞网络编程是编写高性能并发网络服务程序的主流模式,头一次使用这种模式编程需要转换思维模式 .把原来的"主动调用recv()来接收数据,主动调用accept()来接受连接,主动调 ...
- tcp 网络编程
网络编程同时也是进程间的一种通信:服务器进程和应用进程间的通信. OSI:开放式系统互联 OSI 7层模型: ...
随机推荐
- linux终端命令行缩短显示路径
1,修改.bashrc文件(用户根目录下) vim 打开.bashrc文件,找到如下这行: else PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ ...
- python之将Unicode文本标准化
在需要比较字符串的程序中使用字符的多种表示会产生问题. 为了修正这个问题,你可以使用unicodedata模块先将文本标准化: s1 = 'Spicy Jalape\u00f1o' s2 = 'Spi ...
- Javafx弹窗
在javafx中可能用到一些弹窗,比如点击某个按钮后弹出弹窗提示信息等等 Alert alert = new Alert(AlertType.INFORMATION); alert.setTitle( ...
- 结对编程收获——UI真的没有那么简单
结对编程收获——UI真的没有那么简单 詹元成 初看作业要求,心里还有一点欣喜,不就是做一个UI ...
- NetCore利用CsvHelper解析支付宝对账单
支付宝账单是zip压缩文件流,里面包含了两个.csv文件. 1.请求支付宝账单下载链接,获取到zip文件流. var httpClient = _clientFactory.CreateClient( ...
- dill:解决python的“AttributeError: Can't pickle local object”及无法pickle lambda函数的问题
python的pickle是用来序列化对象很方便的工具,但是pickle对传入对象的要求是不能是内部类,也不能是lambda函数. 比如尝试pickle这个内部类: 结果会报错AttributeErr ...
- vue 重定向
//重定向 { path: '/*', component: Home}
- Qt 【遍历文件夹文件,为listwidgetItem设置图标】
效果图如上,通过qt本身的api去获取文件夹中文件的信息并且将其显示到listwidget上.只遍历当前文件夹的文件, 若文件夹中的子文件夹含有符合筛选器的文件那么并不会一同筛选出来 参考百度:htt ...
- 计算机网络之IP地址与MAC地址
IP地址 IP地址(Internet Protocol Address): 缩写为IP Adress,是一种在Internet上的给主机统一编址的地址格式,也称为网络协议(IP协议)地址. 它为互联网 ...
- PHP ftp_cdup() 函数
定义和用法 ftp_cdup() 函数把当前目录改变为 FTP 服务器上的父目录. 如果成功,该函数返回 TRUE.如果失败,则返回 FALSE. 语法 ftp_cdup(ftp_connection ...