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

基于TCP协议的网络通信

        TCP即传输控制协议,基于TCP协议的网络通信总是面向连接的,在通信过程中需要进行“三次握手,四次挥手”,这是众所周知的,所以这里不过多赘述。我们都知道TCP协议传输数据比较稳定,那么为什么稳定,通过本文的代码实现来一探究竟。

        首先来看一下基于TCP协议的网络通信模型:

服务器客户端
创建socket对象创建socket对象

准备通信地址

(端口号+本机IP地址)

准备通信地址

(服务器的公网IP)

绑定socket与通信地址——
设置监听和排队数量——
等待客户端连接连接服务器
分配新的socket对象+开辟新进程或线程——
接收请求发送请求
响应请求接收响应
关闭socket关闭socket

现在有了TCP网络通信模型,那我们按照模型来实现即可,服务器的代码如下:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/un.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <netinet/in.h>typedef struct sockaddr *SP;void server(int cli_fd)
{char buf[4096];size_t buf_size=sizeof(buf);while(1){//接收请求//int ret=read(cli_fd,buf,buf_size);int ret=recv(cli_fd,buf,buf_size,0);if(ret<=0||0==strcmp("quit",buf)){printf("客户端%d退出\n",cli_fd);break;}printf("from %d recv:%s bits:%d\n",cli_fd,buf,ret);//响应请求//把传过来的数据拼接":return"后送回给客户端strcat(buf,":return");ret=send(cli_fd,buf,strlen(buf)+1,0);//ret=write(cli_fd,buf,strlen(buf)+1);if(ret<=0){printf("客户端%d退出\n",cli_fd);break;}}//关闭close(cli_fd);exit(0);
}int main(int argc,const char* argv[])
{//创建socketint sockfd=socket(AF_INET,SOCK_STREAM,0);if(sockfd<0){perror("socket");return -1;}//准备通信地址struct sockaddr_in addr={};addr.sin_family=AF_INET;addr.sin_port=htons(8866);addr.sin_addr.s_addr=inet_addr("192.168.110.12");socklen_t addrlen=sizeof(addr);//绑定if(bind(sockfd,(SP)&addr,addrlen)){perror("bind");return -1;}//监听if(listen(sockfd,5)){perror("listen");return -1;}while(1){//等待连接struct sockaddr_in src_addr={};int cli_fd=accept(sockfd,(SP)&src_addr,&addrlen);if(cli_fd<0){perror("accept");continue;}//创建进程服务if(0==fork()){server(cli_fd);}}return 0;
}

客户端的代码如下:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/un.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <netinet/in.h>typedef struct sockaddr *SP;int main(int argc,const char* argv[])
{//创建socketint cli_fd=socket(AF_INET,SOCK_STREAM,0);if(cli_fd<0){perror("socket");return -1;}//准备通信地址struct sockaddr_in addr={};addr.sin_family=AF_INET;addr.sin_port=htons(8889);addr.sin_addr.s_addr=inet_addr("192.168.110.2");socklen_t addrlen=sizeof(addr);//连接服务器if(connect(cli_fd,(SP)&addr,addrlen)){perror("connect");return -1;}char buf[4096];size_t buf_size=sizeof(buf);while(1){//发送请求printf(">>>>>");scanf("%s",buf);int ret=send(cli_fd,buf,strlen(buf)+1,0);//ret=write(cli_fd,buf,strlen(buf)+1);if(ret<=0){printf("服务器正在升级,请稍后重试\n");break;}if(0==strcmp("quit",buf)){printf("通信结束\n");break;}//接收请求//int ret=read(cli_fd,buf,buf_size);ret=recv(cli_fd,buf,buf_size,0);if(ret<=0){printf("服务器正在维护,请稍候重试\n");break;}printf("read:%s bits:%d\n",buf,ret);}return 0;
}

下面来运行测试一下双端的通信情况:

over


http://www.mrgr.cn/news/34253.html

相关文章:

  • Android OpenGLES2.0开发(二):环境搭建
  • 塑料清洗加工污水处理具体流程和效果说明
  • 为什么越来越多的网工运维转行网络安全?_idc运维转网络安全工程师_系统运维转行网安
  • 【行为树】01-第一棵树
  • 商标管理软件如何助力企业实现商标数字化管理?
  • 怎么录屏?免费录屏软件推荐,电脑屏幕与摄像头内容录制与分享指南
  • tomcat项目【jvm内存溢出】
  • 大数据新视界 --大数据大厂之 Vue.js 与大数据可视化:打造惊艳的数据界面
  • Spring AOP - 注解方式实现
  • Redis Sorted Set 跳表的实现原理和分析
  • 简单使用tesseract-ocr提取图片中的文字
  • angular封装好的组件的收到原生输入框的change事件
  • 可编辑PPT | 能源企业数字化框架、数字化运营及数字化平台建设方案
  • 石头剪刀布手势识别系统源码分享
  • 图论(dfs深搜系列)9.23
  • 甩锅笔记:好好的服务端应用突然起不来,经定位是无法访问外网了?测试又说没改网络配置,该如何定位?
  • 基于Ambari搭建hadoop生态圈+Centos7安装教程V2.0优化版(本篇博客写的较为详细,可能比较多,请耐心看)
  • 【BetterBench博士】2024年华为杯E题:高速公路应急车道紧急启用模型 Python代码实现
  • 最适配达梦、人大金仓的sql工具是什么?
  • HTTP代理域名解析的先后顺序:深入解析