【网络编程】基于TCP的服务器端/客户端

2024-06-13 02:12

本文主要是介绍【网络编程】基于TCP的服务器端/客户端,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

TCP是Transmission Control Protocol(传输控制协议)简写。因为TCP套接字是面向连接的,因此又称为基于流的套接字。

把协议分为多个层次,设计更容易,通过标准化操作设计开放式系统

网络层介绍

链路层

链路层是物理连接领域标准化的结果,是最基本的领域,专门定义LAN,WAN,MAN等网络标准。

IP层

选择传输数据的路径。IP是面向消息的、不可靠的协议。每次传输数据会帮选择一条路径,但并不一致,若发送路径错误则选择其他路径;若发送数据丢失或错误则无法解决。IP协议无法应对数据错误。

TCP/UDP层

TCP和UDP层以IP层提供的路径信息为基础完成实际的数据传输,故该层又称为传输层。

IP层只关注一个数据包的传输过程。传输顺序以及传输本身不可靠,添加TCP可以在交换数据过程确认对方已经收到数据,并重传丢失数据,这类通信是可靠的。

应用层

数据传输路径、数据确认过程都被隐藏到套接字内部,只需利用套接字编出程序即可。编写软件过程中,需要根据程序特点决定服务器端和客户端之间的数据传输规定,这边是应用层协议。

实现基于TCP的服务器端/客户端

调用socket函数创建套接字,声明并初始化地址信息信息结构体变量,调用bind函数向套接字分配地址如上章所示。

通过调用listen函数进入等待连接请求状态,只有调用listen函数客户端才能进入可发出连接请求的状态,即调用connect函数。

#include<sys/socket.h>
int listen(int sock,int backlog);
//成功返回0,失败返回-1

参数:sock希望进入等待连接请求状态的套接字文件描述符,传递的描述符套接字成为服务器套接字(监听套接字)。backlog连接请求等待队列。

服务器端处于等待连接请求状态是指,客户端请求连接时,受理前一直使请求处于等待状态。

客户端如果向服务器端询问:“请问我是否可以发起连接?”服务器端套接字就会亲切应答:“您好!当然可以,但系统正忙,请到等候室排号等待,准备好后会立即受理您的连接。”同时将连接请求请到等候室。调用listen函数即可生成这种门卫(服务器端套接字),listen函数的第二个参数决定了等候室的大小。等候室称为连接请求等待队列,准备好服务器端套接字和连接请求等待队列后,这种可接收连接请求的状态称为等待连接请求状态。

受理客户端连接请求

#include<sys/socket.h>
int accept(int sock,struct sockaddr * addr, socklen_t * addrlen);

sock:服务器套接字的文件描述符。
addr:保存发起连接请求的客户端地址信息的变量地址值,调用函数后向传递来的地址变量参数填
充客户端地址信息。
addrlen:第二个参数addr结构体的长度,但是存有长度的变量地址。函数调用完成后,该变量即被填入客户端地址长度。

TCP客户端得默认函数调用顺序

#include<sys/socket.h>
int connect(int sock,struct sockaddr * servaddr,socklen_t addrlen);

sock---------客户端套接字文件描述符。
servaddr----保存目标服务器端地址信息的变量地址值。
eaddrlen-----以字节为单位传递已传递给第二个结构体参数servaddr的地址变量长度。

函数返回情况:1.服务器端接收连接请求    2.发生断网等异常情况而中断连接请求

注意:接受连接并不意味着服务器端调用acccpet函数,是服务器将连接请求记录到等待队列。

客户端套接字地址信息

实现服务端必给套接字分配IP地址和端口号,但客户端实现过程未出现,而是创建套接字后立即调用connect函数。网络数据交换必须分配IP和端口号,怎么?

客户端分配地址:

  • 何时:调用connect函数时
  • 何地:操作系统,内核
  • 如何:IP用计算机(主机)的IP,端口随机。

基于TCP的服务器端/客户端函数调用关系

流程:服务器端创建套接字后连续调用bind、listen函数进入等待状态,客户端通过调用connect函数发起连接请求。注意:服务器端调用listen函数才能调用connect函数。且客户端调用connect函数前,服务器端有可能率先调用accept函数。此时服务器在调用accept函数时进入阻塞状态,知道客户端调用connect函数为止。

实现迭代服务器端/客户端

服务器端将客户端传输的字符串数据原封不动地传回客户端。

实现迭代的服务器端

服务器端在同一时刻只与一个客户端相连,并提供回声服务。

服务器端依次向5个客户端提供服务并退出。

客户端接收用户输人的字符串并发送到服务器端。

服务器端将接收的字符串数据传回客户端,即“回声”服务器端与客户端之间的字符串回声一直执行到客户端输人Q为止。

存在问题:“每次调用read、write函数时都会以字符串为单位执行实际的/O操作。”
当然,每次调用write函数都会传递1个字符串,因此这种假设在某种程度上也算合理。“TCP不存在数据边界“。上述客户端是基于TCP的,因此,多次调用write函数传递的字符串有可能一次性传递到服务器端。此时客户端有可能从服务器端收到多个字符串,这不是我们希望看到的结果。还需考虑服务器端的如下情况:字符串太长,需要分2个数据包发送!在此过程中,客户端有可能在尚未收到全部数据包就调用read函数。

回声客户端传输的是字符串,且是通过调用write函数一次性发送的。之后还调用一次read函数,期待接收自己传输的字符串。问题所在。

解决方法,可以提前确定接收数据的大小。若之前传输了20字节长的字符串,则在接收时循环调用read函数读取20个字节。

若问题不在回声客服端:定义应用层协议

回声客户端可以提前知道接收的数据长度,但我们应该意识到,更多情况下这不太可能。既然如此,若无法预知接收数据长度时应如何收发数据?此时需要的就是应用层协议的定义。之前的回声服务器端/客户端中定义了如下协议。
        “收到Q就立即终止连接。”

同样,收发数据过程中也需定好规则以表示数据的边界,或提前告知收发数据的大小。服务器端/客户端实现过程中逐步定义的这些规则集合就是应用层协议。

这篇关于【网络编程】基于TCP的服务器端/客户端的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1056000

相关文章

如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解

《如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解》:本文主要介绍如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别的相关资料,描述了如何使用海康威视设备网络SD... 目录前言开发流程问题和解决方案dll库加载不到的问题老旧版本sdk不兼容的问题关键实现流程总结前言作为

使用Java实现获取客户端IP地址

《使用Java实现获取客户端IP地址》这篇文章主要为大家详细介绍了如何使用Java实现获取客户端IP地址,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 首先是获取 IP,直接上代码import org.springframework.web.context.request.Requ

C#多线程编程中导致死锁的常见陷阱和避免方法

《C#多线程编程中导致死锁的常见陷阱和避免方法》在C#多线程编程中,死锁(Deadlock)是一种常见的、令人头疼的错误,死锁通常发生在多个线程试图获取多个资源的锁时,导致相互等待对方释放资源,最终形... 目录引言1. 什么是死锁?死锁的典型条件:2. 导致死锁的常见原因2.1 锁的顺序问题错误示例:不同

PyCharm接入DeepSeek实现AI编程的操作流程

《PyCharm接入DeepSeek实现AI编程的操作流程》DeepSeek是一家专注于人工智能技术研发的公司,致力于开发高性能、低成本的AI模型,接下来,我们把DeepSeek接入到PyCharm中... 目录引言效果演示创建API key在PyCharm中下载Continue插件配置Continue引言

Python手搓邮件发送客户端

《Python手搓邮件发送客户端》这篇文章主要为大家详细介绍了如何使用Python手搓邮件发送客户端,支持发送邮件,附件,定时发送以及个性化邮件正文,感兴趣的可以了解下... 目录1. 简介2.主要功能2.1.邮件发送功能2.2.个性签名功能2.3.定时发送功能2. 4.附件管理2.5.配置加载功能2.6.

SSID究竟是什么? WiFi网络名称及工作方式解析

《SSID究竟是什么?WiFi网络名称及工作方式解析》SID可以看作是无线网络的名称,类似于有线网络中的网络名称或者路由器的名称,在无线网络中,设备通过SSID来识别和连接到特定的无线网络... 当提到 Wi-Fi 网络时,就避不开「SSID」这个术语。简单来说,SSID 就是 Wi-Fi 网络的名称。比如

Java实现任务管理器性能网络监控数据的方法详解

《Java实现任务管理器性能网络监控数据的方法详解》在现代操作系统中,任务管理器是一个非常重要的工具,用于监控和管理计算机的运行状态,包括CPU使用率、内存占用等,对于开发者和系统管理员来说,了解这些... 目录引言一、背景知识二、准备工作1. Maven依赖2. Gradle依赖三、代码实现四、代码详解五

Redis连接失败:客户端IP不在白名单中的问题分析与解决方案

《Redis连接失败:客户端IP不在白名单中的问题分析与解决方案》在现代分布式系统中,Redis作为一种高性能的内存数据库,被广泛应用于缓存、消息队列、会话存储等场景,然而,在实际使用过程中,我们可能... 目录一、问题背景二、错误分析1. 错误信息解读2. 根本原因三、解决方案1. 将客户端IP添加到Re

SpringBoot实现websocket服务端及客户端的详细过程

《SpringBoot实现websocket服务端及客户端的详细过程》文章介绍了WebSocket通信过程、服务端和客户端的实现,以及可能遇到的问题及解决方案,感兴趣的朋友一起看看吧... 目录一、WebSocket通信过程二、服务端实现1.pom文件添加依赖2.启用Springboot对WebSocket

QT实现TCP客户端自动连接

《QT实现TCP客户端自动连接》这篇文章主要为大家详细介绍了QT中一个TCP客户端自动连接的测试模型,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录版本 1:没有取消按钮 测试效果测试代码版本 2:有取消按钮测试效果测试代码版本 1:没有取消按钮 测试效果缺陷:无法手动停