3、基于流式套接字——TCP网络编程

**关于TCP编程中的流式套接字说明**
	TCP编程中的流式套接字sockfd分为两种类型:主动生成和被动生成。主动生成是指通过socket函数生成的流式
套接字。服务器端通过socket函数创建的流式套接字通过bind函数变为监听套接字之后用于监听和接收客户端的连接
请求;客户端通过socket函数创建的流式套接字用于向服务器发送连接请求。被动生成的套接字是当客户端向服务器
发送连接请求之后,服务器通过accept函数接收连接请求时返回的通信套接字,它主要用于服务器与客户端之间的通
信息。
	监听套接字:是服务器端用于监听请求队列的套接字,不能用于和客户端之间的通信。socket函数创建的流式
套接字通过bind函数之后变为监听套接字。
	通信套接字:它是accept函数的返回值,用于服务器与客户端之间的通信。多个客户端与服务器之间进行通信
是在不同的通信套接字上进行的。假设有3个客户端与服务器之间进行通信,则服务器上有4个套接字文件描述符。其
中一个监听套接字,3个通信套接字。
	流式套接字、监听套接字、通信套接字的区分主要是为了进行分工。


服务器和客户端使用TCP的流程如下:

在这里插入图片描述

1、socket函数

函数原型:int socket(int family, int type, int protocol);
函数功能:创建一个socket流式套接字。
函数参数:family		协议簇,一般用宏来表示。
					AF_INET,表示使用IPV4协议
					AF_INET6,表示使用IPV6协议
		  type		套接字的类型,通常使用一下三种类型。
		  			SOCK_STREAM,流式套接字,常用于TCP通信中。
		  			SOCK_DGRAM,数据报套接字,常用于UDP通信中。
		  			SOCK_RAW,原始套接字,一般不直接使用,而是用于定义一个协议。
		  protocol	套接字对应的编号,一般常用0(除了原始套接字外)。一般指定了具体的套接字类型的话
		  			就不用再给定套接字对应的编号,但是原始套接字除外。
返回值:成功,则返回创建的流式套接字;失败,则返回-1。

2、bind函数

函数原型:int bind(int sockfd, struct sockaddr *my_addr, int addrlen);
函数功能:将服务器的流式套接字与服务器的地址信息进行绑定,流式套接字转变为监听套接字。
函数参数:sockfd		通过socket函数创建的流式套接字
		 my_addr	需要绑定的服务器的地址信息
		 addrlen	地址长度
返回值:成功,则返回0;失败,则返回-1。
说明:struct sockaddr 是通用地址类型,如果使用IPV4协议进行通信,则需要将struct sockaddr_in进行强制
转换,转换为struct sockaddr类型。

3、listen函数

函数原型:int listen(int listen_fd, int backlog);
函数功能:监听客户端的连接请求
函数参数:listen_fd		服务器端监听套接字文件描述符
		 backlog		请求队列中允许的最大请求数
返回值:成功,则返回0;失败,则返回-1

4、accept函数

函数原型:int accept(int listen_fd, struct sockaddr_in *addr, socklen_t *addr);
函数功能:接收请求队列中客户端的连接请求,如果请求队列中无请求,则accept函数一直阻塞。
函数参数:listen_fd		监听套接字文件描述符
		 addr			用来保存客户端的地址信息
		 addrlen		地址长度指针
函数返回值:成功,则返回被动分配的通信套接字用于服务器与客户端之间进行通信。
		   失败,则返回-1。

5、connect函数

函数原型:int connect(int client_fd, struct sockaddr *serv_addr, int addrlen);
函数功能:客户端通过connect函数向服务器发送连接请求
函数参数:client_fd		客户端通过socket函数创建的流式套接字
		 serv_addr		存放服务器的地址信息,用于去连接服务器
		 addrlen		地址长度
返回值:成功,则返回0;失败,则返回-1

6、recv、read函数

1、read函数:
函数原型:size_t read(int fd, void *buf, size_t count);
函数功能:“期望”从文件描述符fd相关联的文件中读取count个字节的数据存放在缓冲区buf中。
参数:fd		文件描述符
	 buf	存放读取到的数据的缓冲区首地址
	 count	“期望”读取的字节数
返回值:> 0	表示成功读到的字节数
	    =0	表示读取到了文件的尾部
  	    -1	读取失败,返回-1,并设置errno

(1)read函数说明:
1)读取某个文件的方式
while(ret > 0){
	读取文件;
}
分析:当读取到文件的尾部时ret = 0;当读取文件失败ret == -1;因此读取某个文件的条件是ret > 0
2)read读取文件至少循环两次:
	首先,把文件中的所有数据全部读取完毕,返回读取到的字节数;其次,从文件尾部开始读取,读到了文件
末尾,返回0。


2、recv函数
函数原型:int recv(int connect_fd, void *buf, int size, unsigned int flags);
函数功能:读取通信套接字中的数据
函数参数:connect_fd		通信套接字文件描述符
		 buf			存放接收数据的缓冲区
		 size			“期望”接收数据的大小。一般 sizeof(buf)-1
		 flags			标志位,一般为0,以阻塞的方式接收数据;
		 				0,表示以阻塞的方式接收数据;
		 				MSG_DONTWAIT,表示以非阻塞的方式接收数据
		 				MSG_WAITALL,表示“期望”接收size个字节的数据就必须接收这么多
返回值:>0,表示实际接收到的数据字节数;
		=0,表示对方断开了连接(通信的另一方断开了连接)
		=-1,表示本地接收数据发生了错误

7、send、write函数

1、write函数:
函数原型:size_t write(int fd, const void *buf, size_t count);
功能:“期望”将缓冲区buf中存放的数据中的count个字节写入到与文件描述符fd相关联的文件中。
参数:fd		文件描述符
	 buf	数据存放的缓冲区
	 count	“期望”向文件中写入的字节数目,一般count = strlen(buf),有效写入。
返回值:成功,返回实际写入到文件中的字节数;失败,返回-1,并设置errno。


2、send函数:
函数原型:int send(int connect_fd, const void *buf, int len, int flags);
函数功能:向通信套接字中写入数据
函数参数:connect_fd		通信套接字
		 buf			存放发送数据的缓冲区
		 len			发送数据的长度
		 flags			标志位,一般为0,以阻塞的方式写入数据。
		 				0以阻塞的方式发送数据
		 				MSG_DONTWAIT,表示以非阻塞的方式接收数据
		 				MSG_NOSIGNAL,表示当连接异常的时候别发送信号
返回值:>0,表示实际发送数据的字节数;
		=0,表示连接断开(通信的另一方断开了连接)
		=-1,表示数据发送失败(自己的问题)


例1:服务器进程接收数据、客户端进行发送数据,实现基于IPV4、TCP的进程间通信。
服务器端代码:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

客户端代码:

在这里插入图片描述
在这里插入图片描述

运行结果分析如下:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值