linux网络编程:网络socket基础编程(二) TCP

一、概述

  • TCP提供一种面向连接的、可靠字节流服务
  • 全双工通信。
  • 提供流量控制。
  • 许多流行的应用程序如 Telnet、FTP、Rlogin、SMTP都使用TCP。
    在这里插入图片描述
    在这里插入图片描述
  1. 源端和目的端的端口号:用于寻找发端和收端应用进程。这两个值加上IP首部中的源端IP地址和目的端IP地址唯一确定一个TCP连接。
  2. 序号:用来标识从TCP发端向TCP收端发送的数据字节流,它表示在这个报文段中的的第一个数据字节。如果将字节流看作在两个应用程序间的单向流动,则TCP用序号对每个字节进行计数。序号是32 bit的无符号数,序号到达 2^32- 1后又从0开始。
  3. 确认序号:既然每个传输的字节都被计数,确认序号包含发送确认的一端所期望收到的下一个序号。因此,确认序号应当是上次已成功收到数据字节序号加 1。只有ACK标志(下面介绍)为 1时确认序号字段才有效。
  4. 首部长度:给出首部中 32 bit字的数目,一个bit代表首部长度为4字节,bit最大为15,所以首部最多只有60字节。然而,没有任选字段,正常的长度是 20字节。
  5. URG: 紧急指针( u rgent pointer)有效。
  6. ACK: 确认序号有效。
  7. PSH :接收方应该尽快将这个报文段交给应用层。
  8. RST :重建连接。
  9. SYN :同步序号用来发起一个连接。连接建立后该位置1。
  10. FIN: 发端完成发送任务
  11. 窗口大小: TCP的流量控制由连接的每一端通过声明的窗口大小来提供。窗口大小为字节数,起始于确认序号字段指明的值,这个值是接收端正期望接收的字节。窗口大小是一个 16 bit字段,因而窗口大小最大为 6 5 5 3 5字节。
  12. 检验和:覆盖了整个的TCP报文段: TCP首部和TCP数据。这是一个强制性的字段,一定是由发端计算和存储,并由收端进行验证。
  13. 紧急指针:只有当URG标志置1时紧急指针才有效。紧急指针是一个正的偏移量,和序号字段中的值相加表示紧急数据最后一个字节的序号。 TCP的紧急方式是发送端向另一端发送紧急数据的一种方式。
  14. 选项:最常见的可选字段是最长报文大小,又称为 MSS (Maximum Segment Size)。每个连接方通常都在通信的第一个报文段(为建立连接而设置 SYN标志的那个段)中指明这个选项。它指明本端所能接收的最大长度的报文段。
  15. 数据:TCP报文段中的数据部分是可选的。在一个连接建立和一个连接终止时,双方交换的报文段仅有 T C P首部。如果一方没有数据要发送,也使用没有任何数据的首部来确认收到的数据。在处理超时的许多情况中,也会发送不带任何数据的报文段。

二、TCP连接的建立与终止

  • 三次握手连接建立,四次握手连接终止。
    在这里插入图片描述

2.1 连接的建立

在这里插入图片描述

  • 建立连接过程
    在这里插入图片描述

2.2 连接的终止

在这里插入图片描述
连接的终止过程

  1. 客户端向服务器端发送一个FIN,请求断开连接。和SYN一样,一个FIN将占用一个序号。
  2. 服务器端收到FIN后,回发一个ACK,确认序号为收到的序号加 1。
  3. 同时 T C P服务器还向应用程序(即丢弃服务器)传送一个文件结束符。接着这个服务器程序就关闭它的连接,导致它的 TCP端发送一个FIN。
  4. 客户必须发回一个确认,并将确认序号设置为收到序号加1。

三、TCP编程

API参考 linux应用编程:网络socket编程(一) 基础API
在这里插入图片描述

3.1 服务器端程序

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<unistd.h>
#include<netinet/in.h>
#include <errno.h>  
#define PORT 6666
int main(int argc,char **argv)
{
	int ser_sockfd,cli_sockfd;
	int err,n;
	int addlen;
	struct sockaddr_in ser_addr;
	struct sockaddr_in cli_addr;
	char recvline[200],sendline[200];
	
	ser_sockfd=socket(AF_INET,SOCK_STREAM,0);
	if(ser_sockfd==-1)
	{
		printf("socket error:%s\n",strerror(errno));
		return -1;
	}
	
	bzero(&ser_addr,sizeof(ser_addr));
	ser_addr.sin_family=AF_INET;
	ser_addr.sin_addr.s_addr=htonl(INADDR_ANY);
	ser_addr.sin_port=htons(PORT);
	err=bind(ser_sockfd,(struct sockaddr *)&ser_addr,sizeof(ser_addr));
	if(err==-1)
	{
		printf("bind error:%s\n",strerror(errno));
		return -1;
	}
	
	err=listen(ser_sockfd,5);
	if(err==-1)
	{
		printf("listen error\n");
		return -1;
	}
	
	printf("listen the port:\n");
	
	while(1)
	{	
		addlen=sizeof(struct sockaddr);
		cli_sockfd=accept(ser_sockfd,(struct sockaddr *)&cli_addr,&addlen);
		if(cli_sockfd==-1)
		{
			printf("accept error\n");
		}
		while(1)
		{
			printf("waiting for client...\n");
			n=recv(cli_sockfd,recvline,1024,0);
			if(n==-1)
			{
				printf("recv error\n");
			}
			recvline[n]='\0';
			
			printf("recv data is:%s\n",recvline);
			
			printf("Input your words:");
			scanf("%s",&sendline);
			send(cli_sockfd,sendline,strlen(sendline),0);
		}
		close(cli_sockfd);
	}
	
	close(ser_sockfd);
	
	return 0;
}

3.2 客户端程序


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<unistd.h>
#include<netinet/in.h>
#define PORT 6666
int main(int argc,char **argv)
{
	int sockfd;
	int err,n;
	struct sockaddr_in addr_ser;
	char sendline[20],recvline[20];
	
	sockfd=socket(AF_INET,SOCK_STREAM,0);
	if(sockfd==-1)
	{
		printf("socket error\n");
		return -1;
	}
	
	bzero(&addr_ser,sizeof(addr_ser));
	addr_ser.sin_family=AF_INET;
	addr_ser.sin_addr.s_addr=htonl(INADDR_ANY);
	addr_ser.sin_port=htons(PORT);
	err=connect(sockfd,(struct sockaddr *)&addr_ser,sizeof(addr_ser));
	if(err==-1)
	{
		printf("connect error\n");
		return -1;
	}
	
	printf("connect with server...\n");
	
	while(1)
	{
		printf("Input your words:");
		scanf("%s",&sendline);
		
		send(sockfd,sendline,strlen(sendline),0);
	
		printf("waiting for server...\n");
	
		n=recv(sockfd,recvline,100,0);
		recvline[n]='\0';
		
		printf("recv data is:%s\n",recvline);
	}
	
	
	return 0;
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux网络编程TCP/IP基础篇 01TCPIP基础(一) ISO/OSI参考模型 TCP/IP四层模型 基本概念(对等通信、封装、分用、端口) 02TCPIP基础) 最大传输单元(MTU)/路径MTU 以太网帧格式 ICMP ARP RARP 03TCPIP基础(三) IP数据报格式 网际校验和 路由 04TCPIP基础(四) TCP特点 TCP报文格式 连接建立三次握手 连接终止四次握手 TCP如何保证可靠性 05TCPIP基础(五) 滑动窗口协议 UDP特点 UDP报文格式 Linux网络编程socket编程篇 06socket编程(一) 什么是socket IPv4套接口地址结构 网络字节序 字节序转换函数 地址转换函数 套接字类型 07socket编程TCP客户/服务器模型 回射客户/服务器 socket、bind、listen、accept、connect 08socket编程(三) SO_REUSEADDR 处理多客户连接(process-per-conection) 点对点聊天程序实现 09socket编程(四) 流协议与粘包 粘包产生的原因 粘包处理方案 readn writen 回射客户/服务器 10socket编程(五) read、write与recv、send readline实现 用readline实现回射客户/服务器 getsockname、getpeername gethostname、gethostbyname、gethostbyaddr 11socket编程(六) TCP回射客户/服务器 TCP是个流协议 僵进程与SIGCHLD信号 12socket编程(七) TCP 11种状态 连接建立三次握手、连接终止四次握手 TIME_WAIT与SO_REUSEADDR SIGPIPE 13socket编程(八) 五种I/O模型 select 用select改进回射客户端程序 14socket编程(九) select 读、写、异常事件发生条件 用select改进回射服务器程序。 15socket编程(十) 用select改进第八章点对点聊天程序 16socket编程(十一) 套接字I/O超时设置方法 用select实现超时 read_timeout函数封装 write_timeout函数封装 accept_timeout函数封装 connect_timeout函数封装 17socket编程(十) select限制 poll 18socket编程(十三) epoll使用 epoll与select、poll区别 epoll LT/ET模式 19socket编程(十四) UDP特点 UDP客户/服务基本模型 UDP回射客户/服务器 UDP注意点 20socket编程(十五) udp聊天室实现 21socket编程(十六) UNIX域协议特点 UNIX域地址结构 UNIX域字节流回射客户/服务 UNIX域套接字编程注意点 22socket编程(十七) socketpair sendmsg/recvmsg UNIX域套接字传递描述符字 Linux网络编程之进程间通信篇 23进程间通信介绍(一) 进程同步与进程互斥 进程间通信目的 进程间通信发展 进程间通信分类 进程间共享信息的三种方式 IPC对象的持续性 24进程间通信介绍() 死锁 信号量 PV原语 用PV原语解决司机与售票员问题 用PV原语解决民航售票问题 用PV原语解决汽车租赁问题 25System V消息队列(一) 消息队列 IPC对象数据结构 消息队列结构 消息队列在内核中的表示 消息队列函数 26System V消息队列() msgsnd函数 msgrcv函数 27System V消息队列(三) 消息队列实现回射客户/服务器 28共享内存介绍 共享内存 共享内存示意图 管道、消息队列与共享内存传递数据对比 mmap函数 munmap函数 msync函数 29System V共享内存 共享内存数据结构 共享内存函数 共享内存示例 30System V信号量(一) 信号量 信号量集结构 信号量集函数 信号量示例 31System V信号量() 用信号量实现进程互斥示例 32System V信号量(三) 用信号集解决哲学家就餐问题 33System V共享内存与信号量综合 用信号量解决生产者消费者问题 实现shmfifo 34POSIX消息队列 POSIX消息队列相关函数 POSIX消息队列示例 35POSIX共享内存 POSIX共享内存相关函数 POSIX共享内存示例 Linux网络编程之线程篇 36线程介绍 什么是线程 进程与线程 线程优缺点 线程模型 N:1用户线程模型 1:1核心线程模型 N:M混合线程模型 37POSIX线程(一) POSIX线程库相关函数 用线程实现回射客户/服务器 38POSIX线程() 线程属性 线程特定数据 39POSIX信号量与互斥锁 POSIX信号量相关函数 POSIX互斥锁相关函数 生产者消费者问题 自旋锁与读写锁介绍 40POSIX条件变量 条件变量 条件变量函数 条件变量使用规范 使用条件变量解决生产者消费者问题 41一个简单的线程池实现 线程池性能分析 线程池实现

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值