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

TCP和UDP的代码实现

引言

本片文章是基于一定网络编程基础来实现的TCP和UDP的基本架构,实现了服务端和客户端的代码

TCP

对于TCP来说,它的优势就是在于对于传递信息十分的准确,因为它存在了三次握手和四次挥手的机制,但是缺点也就是每一次信息的传递要消耗大量的资源,来保证每一次传递信息的准确性。

我们可以简单的模拟一下TCP通信的过程,方便我们代码的构架:

首先作为服务器,我们应该先创建一个套接字(socket()),接受来自客户端那一边的连接请求。但是套接字这个仅仅是一个载体,这个载体就是属于谁,性质是什么,都没有确定,所以服务器必须要绑定(bind())这一个载体,然后当一切准备就绪了之后,服务器就要开始监听(listen()),因为我们创建载体的目的就是为了监听客户端。这个监听是存在一个队列的,也就是如果有多个客户端请求服务器,那么这些客户端就会放在这个等待队列里面,等待这服务器的处理。我们一般设置这个队列的长度是128。

然后当我们服务器从队列里面取出一个任务的时候,accept()就会创建出一个新的套接字,这个套接字和最开始的不是一个东西,这个是专门用来和取出来的客户端进行沟通的,然后沟通的方式就是recv和send,作为数据的收发~~~

然后作为客户端,我们不需要监听,而是connect,因为客户端是连接服务器的。

这个是服务器端,首先就是sin结构体的初始化,我们选择的是ipv4,TCP通信,地址是本机的地址

#include <iostream> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #define SER_PORT 8888 #define SER_IP "192.168.189.134" int main() { int sfd = socket(AF_INET, SOCK_STREAM, 0); if (sfd == -1) { perror("socket error"); return -1; } sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = htons(SER_PORT); sin.sin_addr.s_addr = inet_addr(SER_IP); if(bind(sfd, (struct sockaddr *)& sin, sizeof(sin)) == -1) { perror("bind error"); return -1; } if(listen(sfd, 128) == -1) { perror("listen error"); return -1; } sockaddr_in cin; socklen_t sockLen = sizeof(cin); int newfd = accept(sfd, (struct sockaddr *)& cin, &sockLen); if (newfd == -1) { perror("accept error"); return -1; } char rbuf[1024]; while(1) { bzero(rbuf, sizeof(rbuf)); int res = recv(newfd, rbuf, sizeof(rbuf), 0); // 阻塞接受数据 if(res == -1) { perror("recv error"); return -1; } if(res == 0) { std::cout << "client close" << std::endl; break; } strcat(rbuf,"*_*"); if(send(newfd, rbuf, strlen(rbuf), 0) == -1) { perror("send error"); return -1; } } close(newfd); close(sfd); return 0; }

然后对于客户端,我们其实不需要填写cin的任何信息,因为我们只需要连接客户端,然后发送信息,或者接受信息,服务器不需要知道我们客户端的信息,所以bind也是不需要的,不过写了也没错,主要是通过socket这个套接字,来和服务器联系。

#include <iostream> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #define SER_PORT 8888 #define SER_IP "192.168.189.133" #define CLI_PORT 9999 #define CLI_IP "192.168.189.133" int main() { int cfd = socket(AF_INET, SOCK_STREAM, 0); if (cfd == -1) { perror("socket error"); return -1; } sockaddr_in cin; cin.sin_family = AF_INET; cin.sin_port = htons(CLI_PORT); // 客户端的地址可以选择不写,因为客户端是主动连接别人的 if (bind(cfd, (struct sockaddr *)& cin, sizeof(cin)) == -1) { perror("bind error"); return -1; } sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = htons(SER_PORT); sin.sin_addr.s_addr = inet_addr(SER_IP); if(connect(cfd, (struct sockaddr *)& sin, sizeof(sin)) == -1) { perror("connect error"); return -1; } char wbuf[128] = ""; while(1) { bzero(wbuf, sizeof(wbuf)); fgets(wbuf, sizeof(wbuf), stdin); wbuf[strlen(wbuf) - 1] = 0; if (send(cfd, wbuf, strlen(wbuf), 0) == -1) { std::cout << "send error" << std::endl; break; } if (recv(cfd, wbuf, sizeof(wbuf), 0) == -1) { std::cout << "recv error" << std::endl; break; } std::cout << wbuf << std::endl; } close(cfd); return 0; }

UDP

UDP的特点就是保证信息传递要快,不是很看重信息的准确性,所以UDP是面向无连接的,也就是说不管你在不在线,只要我知道你的地址,不需要连接,就可以直接把信息发送过去。

所以缺点也就是信息可能会出现错误,这种通信一般就是在广播方面的应用

服务器端这一部分TCP有区别,首先就是必须要传递cin,也就是客户端的信息,但是这个cin不需要初始化,当客户端那边连接了服务器端之后,cin就会接受客户端的数据,然后进行通信。这个过程中如果客户端下线了,服务器端的recvfrom会阻塞等待,sendto仍然会发出信息,因为UDP是面向无连接的,不需要知道客户端是否在线。

#include <myhead.h> #define SER_PORT 8888 #define SER_IP "192.168.189.133" int main(int argc, char const *argv[]) { //1、创建用于通信的套接字文件描述符 int sfd = socket(AF_INET,SOCK_DGRAM,0); if(sfd == -1){ perror("socket error"); return -1; } printf("socket success sfd = %d\n",sfd); //2、绑定ip地址和端口号 struct sockaddr_in sin; sin.sin_addr.s_addr = inet_addr(SER_IP); sin.sin_family = AF_INET; sin.sin_port = htons(SER_PORT); if(bind(sfd,(struct sockaddr*)& sin,sizeof(sin)) == -1){ perror("bind error"); return -1; } printf("bind success\n"); //3、数据收发 char rbuf[128] = ""; //定义容器接受对端的地址信息结构体 struct sockaddr_in cin; socklen_t socklen = sizeof(cin); while(1){ bzero(rbuf,sizeof(rbuf)); //从客户端中读取消息 if(recvfrom(sfd,rbuf,sizeof(rbuf),0,(struct sockaddr*)&cin, &socklen) == -1){ perror("recvfrom error\n"); return -1; } printf("[%s : %d] : %s\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),rbuf); //加个笑脸发给对方 strcat(rbuf,"*_*"); //将数据发送给客户端 sendto(sfd,rbuf,strlen(rbuf),0,(struct sockaddr*)&cin,sizeof(cin)); printf("发送成功\n"); } //4、关闭套接字 close(sfd); return 0; }

这是客户端的代码,因为没有connect()函数了,所以这里我们发送信息的时候需要传递sin的结构体,保证客户端知道这个数据要传递给谁。但是至于接受数据,其实nullptr就可以,因为接收数据并不需要知道服务器的信息。

#include <iostream> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #define CLI_PORT 9999 #define SER_PORT 8888 #define SER_IP "192.168.189.134" #define CLI_IP "192.168.189.134" int main() { int cfd = socket(AF_INET, SOCK_DGRAM, 0); if (cfd == -1) { perror("socket error"); return -1; } sockaddr_in cin; cin.sin_family = AF_INET; cin.sin_port = htons(CLI_PORT); cin.sin_addr.s_addr = inet_addr(CLI_IP); if (bind(cfd, (struct sockaddr *)& cin, sizeof(cin)) == -1) { perror("bind error"); return -1; } char wbuf[128] = ""; sockaddr_in sin; sin.sin_addr.s_addr = inet_addr(SER_IP); sin.sin_port = htons(SER_PORT); sin.sin_family = AF_INET; while(1) { bzero(wbuf, sizeof(wbuf)); fgets(wbuf, sizeof(wbuf), stdin); wbuf[strlen(wbuf) - 1] = 0; sendto(cfd, wbuf, strlen(wbuf), 0, (struct sockaddr *)& sin, sizeof(sin)); recvfrom(cfd, wbuf, sizeof(wbuf), 0, nullptr, nullptr); std::cout << wbuf << std::endl; } close(cfd); return 0; }

总结

本片文章到这里就结束了,希望可以帮助大家对两种通信方式有更好的理解~~~

http://www.gsyq.cn/news/1536360.html

相关文章:

  • 2026保姆级EPS转PDF教程!在线/PS/AI/Python全方法汇总 - 办公小帮手
  • 3大核心功能深度解析:Scan Tailor如何让扫描文档处理效率提升500%
  • Docker,容器,容器化,DevOps,虚拟化
  • PingFangSC跨平台字体架构:现代Web应用的中文字体解决方案
  • 福州奢侈品黄金回收商家实力榜单2026综合测评:综合实力榜首花落谁家 - 奢侈品回收评测
  • 普通学生学AI,重点是把工具变成解决问题的能力
  • 2026 智能外呼系统实测排行:综合能力出众,数企 AI 成企业降本优选 - 兔兔不是荼荼
  • 索尼AI乒乓球机器人如何推动物理AI技术发展
  • 2026珠海甲醛治理品牌测评:海景房高盐高湿环境7大技术指标实测,谁扛得住回南天 - 环保除醛知识库
  • 2026年青岛品牌首饰回收TOP榜|七家机构硬核实测 添价收黄金奢侈品回收最值得托付 - 薛定谔的梨花猫
  • 2026年西安企业高新技术认定与知识产权保护全攻略:五大服务机构深度对标 - 精选优质企业推荐官
  • 数字创作者必备:微观法律合规与知识产权保护实操指南
  • 3分钟掌握B站缓存视频转换:m4s-converter无损合并全攻略
  • iotdb 安装和 ai预测
  • 国内高含金量知名半导体博览会盘点:一场覆盖全产业链的行业盛宴 - 品牌2026
  • 2026沈阳黄金回收避坑终极攻略!内行私藏靠谱门店清单 - 奢侈品回收评测
  • 赛马娘DMM版终极本地化指南:3分钟实现中文界面与性能优化
  • 如何发起最美幼师微信评选活动?零刷票零投诉保姆级教程,班主任亲测有效(附避坑指南) - 微信投票小程序
  • 共享单车需求预测:时间特征工程 + 随机森林,R² 达到 0.931
  • 行业白皮书配套门店测评榜单,上海全域上门,全品类回收高效回款 - 禹竞
  • 2026淮安装修公司综合实力TOP7 正规家装企业年度榜单 - 装企自媒体训练营辉哥
  • 永州贴膜全解析:行业现状、选购避坑指南与本地靠谱门店参考 - 国麟测评
  • 企业级文档自动化:clawPDF虚拟打印机的深度应用指南
  • # 2026年临沂空调移机机构实力排行榜:兰山区河东区罗庄区,基于空调服务的5大权威推荐榜单 - 十大品牌榜
  • 自由创新研究探索:青年研究者的50小时实践方法论
  • MQTT 发布/订阅模式介绍
  • Windows Mobile短信管理工具的嵌入式优化实践
  • # 2026年国内广东广州等地泰茶培训公司实力排行榜:基于餐饮管理的十大权威推荐榜单 - 十大品牌榜
  • 如何用3个步骤拯救你的损坏视频?Untrunc开源工具深度解析
  • 2026年青岛LV包包回收测评:本地靠谱奢侈品变现渠道盘点 - 薛定谔的梨花猫