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

网络编程TCP与UDP

TCP与UDP

UDP头: 

包括源端口、目的地端口、用户数据包长度,检验和  数据。

typedef struct _UDP_HEADER 
{unsigned short m_usSourPort;       // 源端口号16bitunsigned short m_usDestPort;       // 目的端口号16bitunsigned short m_usLength;        // 数据包长度16bitunsigned short m_usCheckSum;      // 校验和16bit
}__attribute__((packed))UDP_HEADER, *PUDP_HEADER;

IP头:

UDP与TCP的区别

TCPUDP
有链接无链接
可靠传输(使用流量控制和拥塞控制)不可靠传输(不使用流量控制和用三个控制)
只能一对一一对一,一对多或者多对多
面向字节流面向报文
首部大小20~60字节首部大小8字节

SOCK_UDP

服务端代码:


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
typedef struct sockaddr * (SA);
int main(int argc, char *argv[])
{int sockfd = socket(AF_INET,SOCK_DGRAM,0);if(-1 == sockfd){perror("socket");exit(1);}// man 7 ip struct sockaddr_in ser,cli;bzero(&ser,sizeof(ser));bzero(&cli,sizeof(cli));ser.sin_family = AF_INET;// 大小端转化 host to net short ser.sin_port = htons(50000);ser.sin_addr.s_addr = inet_addr("192.168.203.128");int ret = bind(sockfd,(SA)&ser,sizeof(ser));if(-1 == ret){perror("bind");exit(1);}socklen_t len = sizeof(cli);while(1){char buf[512]={0};recvfrom(sockfd,buf,sizeof(buf),0,(SA)&cli,&len);time_t tm;time(&tm);sprintf(buf,"%s %s",buf,ctime(&tm));sendto(sockfd,buf,strlen(buf),0,(SA)&cli,len);}close(sockfd);return 0;
}

客户端代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
typedef struct sockaddr * (SA);int main(int argc, char *argv[])
{int sockfd = socket(AF_INET,SOCK_DGRAM,0);if(-1 == sockfd){perror("socket");exit(1);}struct sockaddr_in ser;bzero(&ser,sizeof(ser));ser.sin_family = AF_INET;// 大小端转化 host to net short ser.sin_port = htons(50000);ser.sin_addr.s_addr = inet_addr("192.168.203.128");while(1){char buf[512]="hello,this is udp test";sendto(sockfd,buf,strlen(buf),0,(SA)&ser,sizeof(ser));bzero(buf,sizeof(buf));recvfrom(sockfd,buf,sizeof(buf),0,NULL,NULL);printf("buf is %s\n",buf);sleep(1);}close(sockfd);return 0;
}

网络接口

socket

int socket(int domain, int type , int protocol);

socket作用:创建套接字。

domain: 协议族---> 指定了套接字所使用的协议类型(常用的协议族包括 AF_INET、AF_INET6、AF_UNIX等。其中,AF_INET 表示 IPv4 协议族,AF_INET6 表示 IPv6 协议族,AF_UNIX 表示 Unix 域协议族)

type:套接字类型---> 指定了套接字的数据传输方式(SOCK_STREAM 表示面向连接的流套接字,主要用于可靠传输数据,例如 TCP 协议。SOCK_DGRAM 表示无连接的数据报套接字,主要用于不可靠传输数据,例如 UDP 协议。)

protocol:协议类型--->指定了套接字所使用的具体的协议类型

bind

int bind( (int sockfd, const struct sockaddr *addr, socklen_t addrlen);

bind作用:绑定套接字,将套接字与网络地址绑7定。

sockfd:为套接字描述符。

addr 表示绑定的地址信息。

addrlen 是绑定地址信息的长度。

sendto

发送数据(会阻塞)

int sendto (int s, const void *buf, int len, unsigned int flags, const struct sockaddr *to, int tolen);

sendto作用:把UDP数据包发给指定地址。

s:              socket套接字描述符。
buf:         UDP数据报缓存地址。(把数据放在哪里存储,或者说发送的数据是什么)
len:          UDP数据报长度。(发送长度)
flags:       该参数一般为0。
to:            sendto()函数参数,struct sockaddr_in类型,指明UDP数据发往哪里报。
tolen:      对方地址长度,一般为:sizeof(struct sockaddr_in)。

recvfrom

接收数据(不会阻塞)

int recvfrom(int s, void *buf, int len, unsigned int flags, struct sockaddr *from, int *fromlen);

recvfrom()作用:从指定地址接收UDP数据报。

s:              socket套接字描述符。

buf:         UDP数据报缓存地址。(把数据放在哪里存储,或者说发送的数据是什么)

len:          UDP数据报长度。(接收长度)

fromlen:recvfrom()函数参数,struct sockaddr_in类型,指明从哪里接收UDP数据报。

struct sockaddr_in结构体

struct sockaddr_in {
short int sin_family;                      /* Address family */
unsigned short int sin_port;       /* Port number */
struct in_addr sin_addr;              /* Internet address */
unsigned char sin_zero[8];         /* Same size as struct sockaddr */
};

这个结构体里面包括:
sin_family  //代表协议族  在socket只指AF_INET

sin_port     //存储端口号

sin_addr    //存储IP地址

sin_zero    //是为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节。

listen监听套接字

int listen(int sockfd, int backlog);

功能: 在套接字id上监听等待链接

返回值:成功  0     ;     失败     -1

SOCK_TCP

服务端代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <time.h>
typedef struct sockaddr* (SA);
int main(int argc, char *argv[])
{//监听套接字int listfd =  socket(AF_INET,SOCK_STREAM, 0);if(-1 == listfd){perror("socket");exit(1);}struct sockaddr_in ser,cli;bzero(&ser,sizeof(ser));bzero(&cli,sizeof(cli));ser.sin_family = AF_INET;ser.sin_port = htons(50000);//host to net long ser.sin_addr.s_addr = htonl(INADDR_ANY);int ret = bind(listfd,(SA)&ser,sizeof(ser));if(-1 == ret){perror("bind");exit(1);}//同一时刻三次握手排队数listen(listfd,3);socklen_t  len = sizeof(cli);//通信套接字 int conn = accept(listfd,(SA)&cli,&len);if(-1 == conn){perror("accept");exit(1);}while(1){char buf[512]={0};int rd_ret = recv(conn,buf,sizeof(buf),0);if(rd_ret<=0){// 0  对方断开连接 -1 错误break;}time_t tm;time(&tm);sprintf(buf,"%s %s",buf,ctime(&tm));send(conn,buf,strlen(buf),0);}close(listfd);close(conn);return 0;
}

客户端代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <time.h>
#include <arpa/inet.h>
typedef struct sockaddr* (SA);int main(int argc, char *argv[])
{int sockfd = socket(AF_INET,SOCK_STREAM,0);if(-1 == sockfd){perror("socket");exit(1);}struct sockaddr_in ser;bzero(&ser,sizeof(ser));ser.sin_family = AF_INET;ser.sin_port = htons(50000);//host to net long ser.sin_addr.s_addr = inet_addr("127.0.0.1");int ret = connect(sockfd,(SA)&ser,sizeof(ser));if(-1 == ret){perror("connect");exit(1);}while(1){char buf[512]="hello,this is tcp test";send(sockfd,buf,strlen(buf),0);bzero(buf,sizeof(buf));recv(sockfd,buf,sizeof(buf),0);printf("buf :%s\n",buf);sleep(1);}close(sockfd);return 0;
}

三次握手和四次挥手

TCP建立连接://三次握手

最开始客户端处于closed状态,服务端处于Listen状态。

        第一次握手:客户端发送一个SYN主动打开传输通道,并且说明客户端的初始化序列号ISN,这时客户端处于SYN_SENT状态。

        第二次握手:服务器收到客户端发送的SYN报文之后,会用自己的SYN报文作为应答,也指定了自己的初始化序列号ISN(s),同时还会发送ACK应答给客户端,(ACK = ISN + 1),表示自己收到了客户端的SYN,服务端处于SYN_RCVD状态。

        第三次握手:客户端收到SYN报文之后,会发送一个ACK报文,把服务器的ISN+1作为应答ACK的值,表示接收到了服务端的SYN,此时客户端和服务端都处于ESTABLISHED状态。此时建立起了连接。

三次握手目的

确保客户端和服务端的收发功能都是正常的。

TCP终止连接://四次挥手

客户端和服务端都可以主动发起挥手动作,若客户端先发送关闭请求,则过程如下:

        第一次挥手:客户端发送一个FIN报文,报文指定一个序列号,客户端变成FIN——WAIT1的状态。

        第二次挥手:服务端收到FIN之后,给客户端发送ACK报文,把客户端的序列号+1作为ACK回复,此时服务端进入CLOSE_WAIT状态。

        第三次挥手:服务端也要断开连接时,发送FIN报文+序列号给客户端,此时服务端进入LAST_ACK状态。

        第四次挥手: 服务端收到FIN之后发送ACK =  seq+1回复应答,此时客户端处于TIME_WAIT状态,等一段时间确保服务端收到自己的ACK报文之后才会进入CLOSED状态,而服务端收到应答之后直接进入CLOSED状态。

四次挥手目的

        保证客户端发送的最后一个ACK报文能到达服务端。确保所有的信息都传输完,最后发送结束信号,通知对方信息已经发完了再结束。

查看网络指令(在ubuntu)

1、ifconfig    查看自己的网络配置

2、netstat    -anp       查看当前活动的互联网连接

3、ping   测试网络命令

4、sudo ufw disable/enable             //防火墙关闭/打开

5、sudo apt-get install wireshark    //网络抓包工具   只有网络设备闭上有数据的收发就会放在这。

6、sudo wireshark     //使用抓包工具

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 备战秋招60天算法挑战,Day22
  • I2C通信协议(软件I2C和硬件I2C)
  • 博客园-awescnb插件-geek皮肤优化--公众号卡片
  • Kerberos认证以及黄金票据白银票据的简单介绍
  • 【其它-高效处理小技巧】如何批量备份263企业邮箱邮件之-如何查看.eml
  • C语言程序设计-练习篇
  • 深度优先搜索-放苹果
  • Python OpenCV 影像处理:影像轮廓
  • 详细阐述Android中的四种启动模式
  • 项目问题 | CentOS 7停止维护导致yum失效的解决办法
  • 前端数据存在什么地方,刷新页面之后依旧存在
  • 【数学建模备赛】Ep05:斯皮尔曼spearman相关系数
  • 尚硅谷Java面试题第四季-MySQL面试题
  • 关于武汉芯景科技有限公司的多协议收发芯片XJ526(第二篇RS422模式)开发指南(兼容SP526)
  • Java:循环练习
  • 时间复杂度分析经典问题——最大子序列和
  • 《深入 React 技术栈》
  • Android路由框架AnnoRouter:使用Java接口来定义路由跳转
  • django开发-定时任务的使用
  • DOM的那些事
  • GraphQL学习过程应该是这样的
  • java正则表式的使用
  • k个最大的数及变种小结
  • LeetCode刷题——29. Divide Two Integers(Part 1靠自己)
  • Magento 1.x 中文订单打印乱码
  • pdf文件如何在线转换为jpg图片
  • PHP 使用 Swoole - TaskWorker 实现异步操作 Mysql
  • Python连接Oracle
  • React组件设计模式(一)
  • 猴子数据域名防封接口降低小说被封的风险
  • 技术:超级实用的电脑小技巧
  • 力扣(LeetCode)56
  • 前端每日实战:61# 视频演示如何用纯 CSS 创作一只咖啡壶
  • 如何解决微信端直接跳WAP端
  • 手写双向链表LinkedList的几个常用功能
  • 延迟脚本的方式
  • LIGO、Virgo第三轮探测告捷,同时探测到一对黑洞合并产生的引力波事件 ...
  • Prometheus VS InfluxDB
  • ​数据结构之初始二叉树(3)
  • #数学建模# 线性规划问题的Matlab求解
  • #图像处理
  • $.ajax()参数及用法
  • (3)选择元素——(17)练习(Exercises)
  • (51单片机)第五章-A/D和D/A工作原理-A/D
  • (多级缓存)缓存同步
  • (二)linux使用docker容器运行mysql
  • (接上一篇)前端弄一个变量实现点击次数在前端页面实时更新
  • (每日一问)基础知识:堆与栈的区别
  • (免费领源码)python+django+mysql线上兼职平台系统83320-计算机毕业设计项目选题推荐
  • (七)Java对象在Hibernate持久化层的状态
  • (三) diretfbrc详解
  • (已解决)报错:Could not load the Qt platform plugin “xcb“
  • (转) 深度模型优化性能 调参
  • (转)nsfocus-绿盟科技笔试题目
  • (转)socket Aio demo