基本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层模型: ...
随机推荐
- python之数据序列转换并同时计算数据
问题 你需要在数据序列上执行聚集函数(比如 sum() , min() , max() ), 但是首先你需要先转换或者过滤数据 解决方案 一个非常优雅的方式去结合数据计算与转换就是使用一个生成器表达式 ...
- C语言中各种进制的表示
#include<stdio.h> int main() { //默认情况下是十进制 ; // 二进制(0b或者0B开头) int number2 = 0b1100; //八进制(0开头) ...
- 使用JDBC获取SQL自动增长的ID
在项目开发中,遇到一个问题,先添加一条记录然后想立刻获取这条记录的ID值,ID由SQLServer自动增长的,如果先插入再查询的话,需要另外执行一条查询ID的SQL语句,因此有了下面的方法: 1.使用 ...
- Android开发:Handler的简单使用(一)
1.Handler是什么? 原文: A Handler allows you to send and process Message and Runnable objects associated w ...
- tomcat配置报错解决方法 The jre_home environment variable is not defined correctly
tomcat配置的时候弹出错误,The jre_home environment variable is not defined correctly,难道jre环境变量配置不正确?但是我们又可以执行j ...
- Red Hat 操作系统 rpm 卸载软件提示"error: %preun( ) scriptlet failed, exit status 1"
在linux里安装程序有两种方法,一种是源程序安装,按照安装包里的readme或者install文件指示,一步步地进行,通常是configure, make, install三部曲.另一种就是rpm包 ...
- 2016计蒜之道复赛 百度地图的实时路况 分治+Floyd
题目链接:https://nanti.jisuanke.com/t/A1108 这道题还挺有意思的.让我对Floyd的了解又加深了一点. 首先我们重新审视Floyd这三重循环到底有什么用?第一层是枚举 ...
- Android AppCompatActivity去掉actionbar fullScreen
网上已经有很多关于这个问题的解决方案,如果你试了都没有解决,那么请往下看.首先说下网上说的解决方案: 方案一:在AndroidManifest.xml中,为需要进行全屏显示的activity添加如下主 ...
- java笔试题大全带答案(经典11题)
1.不通过构造函数也能创建对象吗()A. 是B. 否分析:答案:AJava创建对象的几种方式(重要):(1) 用new语句创建对象,这是最常见的创建对象的方法.(2) 运用反射手段,调用java.la ...
- Linux系统关闭对ping命令做响应。
1.测试 ping 192.168.10.5 可以正常ping通, 2,修改 /proc/sys/net/ipv4/icmp_echo_ignore_all 文件的值=1 3.在测试 已经ping不 ...