基本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层模型: ...
随机推荐
- 【目录】循序渐进学.Net Core Web Api开发系列
当前标签: 循序渐进学.Net Core Web Api开发系列 循序渐进学.Net Core Web Api开发系列[16]:应用安全续-加密与解密 NET未来之路 2019-03-13 15: ...
- nginx匹配以XXX结尾的
匹配以do结尾的所有文件:如http://192.168.126.168:8080/delivery/transportPlanData.do?startRelease=2019-07-06& ...
- Nginx+PHP-FPM远程命令执行_CVE-2019-11043
漏洞描述 此次漏洞主要由于 PHP-FPM 中 sapi/ fpm/ fpm/ fpm_main.c 文件内的 env_path_info 下溢导致,攻击者可以使用换行符 %0a 破坏 Nginx 中 ...
- 与JS报错的那段时光
1.Uncaught SyntaxError: Unexpected end of input js报错: 翻译:语法错误:输入意外终止 原因:页面代码写的不规范 ╮(╯▽╰)╭ 其中的某条语句,没 ...
- 项目案例之GitLab的数据迁移
项目案例之GitLab的数据迁移 链接:https://pan.baidu.com/s/1CgaEv12cwfbs5RxcNpxdAg 提取码:fytm 复制这段内容后打开百度网盘手机App,操作更方 ...
- MATLAB中图像处理的函数
表1 图像显示 函数名 功能说明 函数名 功能说明 colorbar 颜色条显示 montage 按矩形剪辑方式显示多帧图像 getimage 从坐标系中获取图像数据 immovie 从多帧索引图像中 ...
- 利用Process类创建多个子进程对象执行任务,主进程负责调度
import time from multiprocessing import Process def run1(): for i in range(5): print("sunck is ...
- (二)Django连接本地mysql异常
Pycharm连接数据库出现错误 管理员身份进入mysql数据库 命令: mysql -u root -p 重新进入mysql 在进入Pycharm发现连接成功
- kubeadm部署多master节点高可用k8s1.16.2
一.架构信息 系统版本:CentOS 7.6 内核:3.10.0‐1062.4.1.el7.x86_64 Kubernetes: v1.16.2 Dockerce: 19.03 推荐硬件配置:2核4 ...
- Java中IO流之字符流
我们有了字节流,为什么还需要字符流? 字符的底层是 字节 + 编码表 = 字符,字符是人能看懂的信息. 字符流在使用的时候,会以字节流为基础,把字节写入缓冲区,在缓冲区内根据编码类型(UTF-8,GB ...