当前位置: 首页 > news >正文

C/S模型测试

1

1.1代码示例

#include<stdio.h>
#include<stdio.h>#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <arpa/inet.h>#include <sys/stat.h>
#include <fcntl.h>#include <unistd.h>#include <string.h>int main(void)
{int sockfd=0;int ret=0;struct sockaddr_in seraddr;char tmpbuff[4096]={"I need some offers"};int cnt=0;ssize_t nsize=0;/* 1 创建网络套接字 */sockfd=socket(AF_INET,SOCK_STREAM,0);if(-1==sockfd){perror("fail to socket");return -1;}/* 2 初始化网络地址结构体 */seraddr.sin_family=AF_INET;seraddr.sin_port=htons(50000);seraddr.sin_addr.s_addr=inet_addr("192.168.1.123");/* 3 发送连接请求 */ret=connect(sockfd,(struct sockaddr *)&seraddr,sizeof(seraddr));if(-1==ret){perror("fail to connect");return -1;}/* 4 客户端与服务器交互 */while(1){
#if 0/* 4.1 清空发送缓冲区 */memset(tmpbuff,0,sizeof(tmpbuff));/* 4.2 拼接数据 */sprintf(tmpbuff,"client send:### %d",cnt);cnt++;/* 4.3 发送数据到网络套接字 */nsize=send(sockfd,tmpbuff,strlen(tmpbuff),0);if(-1==nsize){perror("fail to send");return -1;}
#endif#if 1/* 清空接收缓冲区 */memset(tmpbuff,0,sizeof(tmpbuff));/* 接收网络套接字数据 */nsize=recv(sockfd,tmpbuff,sizeof(tmpbuff),0);if(-1==nsize){perror("fail to recv");return -1;}
#endif/* 显示接收数据 */printf("client recv:### %s\n",tmpbuff);}/* 5 关闭网络套接字 */close(sockfd);return 0;
}int main(void)
{int sockfd=0;struct sockaddr_in seraddr;int ret=0; int confd=0;char tmpbuff[4096]={0};ssize_t nsize=0;/* 1 创建网络套接字 */sockfd=socket(AF_INET,SOCK_STREAM,0);if(-1==sockfd){perror("fail to socket");return -1;}/* 2 初始化网络地址结构体 */seraddr.sin_family=AF_INET;seraddr.sin_port=htons(50000);seraddr.sin_addr.s_addr=inet_addr("192.168.1.123");/* 3 绑定网络套接字 */ret=bind(sockfd,(struct sockaddr *)&seraddr,sizeof(seraddr));if(-1==ret){perror("fail to bind");return -1;}/* 4 监听网络套接字 */ret=listen(sockfd,10);if(-1==ret){perror("fail to listen");return -1;}/* 5 服务器与客户端交互 */while(1){/* 5.1 创建通信套接字-阻塞等待网络套接字连接请求*/confd=accept(sockfd,NULL,NULL);if(-1==confd){perror("fail to accept");return -1;}#if 0/* 5.2 清空接收缓冲区 */memset(tmpbuff,0,sizeof(tmpbuff));/* 5.3 接收通信套接字数据-并做接收完成处理 */nsize=recv(confd,tmpbuff,sizeof(tmpbuff),0);if(-1==nsize){perror("fail to recv");return -1;}else if(0==nsize){return 0;}
#endif/* 5.2 清空发送缓冲区 */memset(tmpbuff,0,sizeof(tmpbuff));/* 5.4 拼接 */sprintf(tmpbuff,"server send:### %s",tmpbuff);/* 5.5 发送 */nsize=send(confd,tmpbuff,strlen(tmpbuff),0);if(-1==nsize){perror("fail to send");return -1;}}/* 6 关闭通信套接字 */close(confd);/* 7 关闭网络套接字 */close(sockfd);return 0;
}

1.2运行结果

(1)运行服务器
(2)运行客户端现象如下:客户端发生阻塞

在这里插入图片描述

(1)关闭服务器:客户端不阻塞-说明recv函数为非阻塞状态

在这里插入图片描述

总结:
(1)如果将服务器accept函数放在while循环内部:同时运行客户端与服务器,可以发现服务器可以与多个客户端建立连接(解决的问题-服务器并发访问)。
(2)但是只能进行一次数据发送(虽然解决了服务器的并发访问问题,但是对于大量的数据传输却手足无措)小意外:当服务器端退出,此时客户端不再阻塞,正常执行函数体。(这就说明了,此时recv函数为非阻塞状态=》那么服务器和客户端同时运行,为什么会发生阻塞?)补充:
(1)如果将服务器端accept函数放在while循环外部(对比TCP文件传输):1)只有一个客户端能够与服务器建立连接并进行数据收发;其它客户端被阻塞,无法与服务器建立连接。(问题:(1)服务器只能与一个客户端建立连接?(2)那么如何解决这个问题?(3)是从服务端解决这个问题,还是从客户端解决这个问题?	先解决问题(3):显然,要解决这个问题肯定是要从服务器端去解决--客户端是向服务器端发起连接请求,那么具体是否能够建立连接,显然是取决于服务器端的意愿和能力;所以,多个客户端向服务器端发起连接请求,能不能实现的关键在于服务器能不能接受多个客户端接入,服务器端是否允许多个客户端接入。	下面再解决问题(2):解决这个问题,其实用一句话来表述就是解决服务器并发访问问题,这个问题后面专项解决,现在只需要明白所面临的问题是服务器并发访问的问题即可。)(2)如果将connect函数放在循环外部,将accept函数放在循环外部,此时意味着:客户端与服务器端第一次建立连接,可以发送一次数据;发完数据接着进行第二次,第三次。。。连接请求;此时当然是报错!因为同一个网络套接字只能建立一次连接,不能重复建立连接(这是由TCP通信机制决定的);但是这种方式可以将服务器同时与多个客户端建立连接。。。。。。。。。。。。。。总结一下就是:客户端与服务器端要进行多次请求连接-建立连接;那么每进行一次通信,都必须关闭(close)通信套接字(已经建立三次握手,四次挥手连接的套接字confd-accept)。

在这里插入图片描述

问题:(1)在客户端或者服务器的

相关文章:

  • 轻松上手Jupyter Notebook:数据分析与可视化的终极指南
  • Django——Admin站点(Python)
  • Linux:confluence8.5.9的部署(下载+安装+破ji)离线部署全流程
  • 网卡配置基础知识
  • 【面试】介绍一下HotSpot虚拟机
  • Jenkins常用插件与应用详解
  • Python中Web开发-Django框架
  • uni-app实现页面通信EventChannel
  • php反序列化学习(2)
  • 代码随想录算法训练营第三十四 |● 1005.K次取反后最大化的数组和 ● 134. 加油站 ● 135. 分发糖果
  • 前端开发:$nextTick()的使用及原理
  • Leetcode 105:从前序与中序遍历序列构造二叉树
  • 大数据中的电商数仓项目:探秘业务的核心
  • 【C++】——string模拟实现
  • GB-T 43206-2023 信息安全技术 信息系统密码应用测评要求
  • 【Leetcode】101. 对称二叉树
  • 时间复杂度分析经典问题——最大子序列和
  • [译] 理解数组在 PHP 内部的实现(给PHP开发者的PHP源码-第四部分)
  • 345-反转字符串中的元音字母
  • Docker下部署自己的LNMP工作环境
  • interface和setter,getter
  • Java IO学习笔记一
  • Javascript 原型链
  • Java比较器对数组,集合排序
  • Joomla 2.x, 3.x useful code cheatsheet
  • REST架构的思考
  • windows下如何用phpstorm同步测试服务器
  • 订阅Forge Viewer所有的事件
  • 对话:中国为什么有前途/ 写给中国的经济学
  • 后端_MYSQL
  • 基于Vue2全家桶的移动端AppDEMO实现
  • 前端js -- this指向总结。
  • 听说你叫Java(二)–Servlet请求
  • Redis4.x新特性 -- 萌萌的MEMORY DOCTOR
  • 阿里云移动端播放器高级功能介绍
  • ​如何使用QGIS制作三维建筑
  • #C++ 智能指针 std::unique_ptr 、std::shared_ptr 和 std::weak_ptr
  • #我与Java虚拟机的故事#连载09:面试大厂逃不过的JVM
  • %3cscript放入php,跟bWAPP学WEB安全(PHP代码)--XSS跨站脚本攻击
  • (1)(1.9) MSP (version 4.2)
  • (2024,LoRA,全量微调,低秩,强正则化,缓解遗忘,多样性)LoRA 学习更少,遗忘更少
  • (delphi11最新学习资料) Object Pascal 学习笔记---第13章第6节 (嵌套的Finally代码块)
  • (pycharm)安装python库函数Matplotlib步骤
  • (Redis使用系列) Springboot 整合Redisson 实现分布式锁 七
  • (二)JAVA使用POI操作excel
  • (分享)自己整理的一些简单awk实用语句
  • (汇总)os模块以及shutil模块对文件的操作
  • (十)Flink Table API 和 SQL 基本概念
  • (十三)MipMap
  • (一)Mocha源码阅读: 项目结构及命令行启动
  • (转)GCC在C语言中内嵌汇编 asm __volatile__
  • (转)重识new
  • (转载)hibernate缓存
  • .net framework profiles /.net framework 配置
  • .NET MAUI Sqlite数据库操作(二)异步初始化方法