TCP与UDP编程以及它们的区别

网络

网络是由若干结点和连接这些结点的链路组成,网络中的结点可以是计算机、交换机、路由器等设备。
网络设备有:交换机、路由器、集线器
传输介质有:双绞线、同轴电缆、光纤

互联网
把多个网络连接起来就构成了互联网。目前最大的互联网就是我们常说的因特网。

IP地址(在网络中唯一标识一台主机)
IP地址就是给因特网上的每一个主机(或路由器)的每一个接口分配的一个在全世界范围唯一的标识符。IP地址因其特殊的结构是我们可以在因特网上很方便地进行寻址。每个IP地址由网络号和主机号构成。
(网络号+主机号一共32位)
IP地址分为IPV4和IPV6两种类别格式,IPV4是类似“A.B.C.D”的格式,是32位的,用“.‘分成四个段,每个段是8个位(0-255)。IPV6地址是128位,格式类似”XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX“,用”:“分成8个段,每个段16位,用4个16进制数表示。

由于每类地址的开头是固定的,因此每类地址都有自己的范围:

A类:IP地址范围为:0.0.0.0~127.255.255.255。
(网络号7位,主机号24位,开头第一位是0)
B类:IP地址范围为:128.0.0.0~191.255.255.255。
(网络号14位,主机号16位,开头前两位是1、0)
C类:IP地址范围为:192.0.0.0~127.223.255.255。
(网络号21位,主机号8位,开头前三位是1、1、0)
在Linux中使用命令”ifconfig“可以查看自己的ip地址。

网络协议:

网络协议就是一组网络规则的集合,是我们共同遵守的约定或标准。常见的协议:
HTTP:超文本传输协议
FTP:文件传输协议
TELNET:是internet远程登录服务的标准协议
TCP:传输控制协议,是一种面向连接的、可靠的、基于字节流的传输层协议
UDP:用户数据报协议
IP:Interner Protocol简称IP,又译为网络协议或互联网协议
ICMP:因特网控制报文协议
ARP:地址解析协议,是根据IP地址获取MAC地址的协议
RARP:逆地址解析协议

网络分层模型
OSI的7层模型与tcp/ip协议族体系的4层结构
OSI模型 tcp/ip模型
应用层 应用层
表示层 传输层
会话层 网络层
传输层 数据链路层
网络层
数据链路层
物理层

分层的好处
1、各层之间是独立的
2、灵活性好
3、结构上可分割开
4、易于实现和维护
5、能促进标准化工作

socket网络编程

1、主机字节序列和网络字节序列
主机字节序列分为大端字节序和小端字节序,不同的主机采用的字节序列可能不同。大端字节序是指整数的高位字节存储在内存的低地址处,而低位字节
存储在内存的高地址处。小端字节序则是指整数的高位字节存储在内存的高地址处,低位字节存储在内存的低地址处。在两台使用不同字节序的主机之间传递数据时,可能会出现冲突。所以,在将数据发送到网络时规定整形数据使用大端字节序,所有也把大端字节序称为网络字节序。

uint32_t htonl(uint32_t hostlong);//长整型的主机字节序转网络字节序
uint32_t ntohl(uint32_t netlong);//长整型的网络字节序转主机字节序
uint16_t htons(uint16_t hostshort);//短整型的主机字节序转网络字节序
uint16_t ntohs(uint16_t netshort);//短整型的网络字节序转主机字节序
in_addr_t inet_addr(const char* cp);//字符串表示的IPV4地址转化为网络字节序
char* inet_ntoa(struct in_addr in);//IPV4地址的网络字节序转换为字符串表示

TCP编程
Linux中
服务器端

#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
int main()
{
	int sockfd = socket(AF_INET,SOCK_STREAM,0);//创建监听套接字
	assert(sockfd != -1);
	struct sockaddr saddr,caddr;
	memset(&saddr,0,sizeof(saddr));
	saddr.sin_family = AF_INET;
	saddr.sin_port = htons(6000);
	saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
	
	int res = bind(sockfd,(struct saddr*)&saddr,sizeof(saddr));//绑定ip和port
	assert(res != -1);
	res = listen(sockfd,5);//设置监听队列长度
	while(1)
	{
		int len = sizeof(caddr);
		int c = accept(sockfd,(struct caddr*)&caddr,&len);//连接套接字
		if(c<0)
		{
			continue;
		}
		while(1)
		{
			int buff[128] = {0};
			int n = recv(c,buff,127,0);
			if(n <= 0)
			{
				break;
			}
			ptintf("buff-%s\n",buff);
			send(c,"ok",2,0);
		}
	}
	close(c);
}

客户端

#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
int main()
{
	int sockfd = socket(AF_INET,SOCK_STREAM,0);
	assert(sockfd != -1);
	struct sockaddr saddr;
	memset(&saddr,0,sizeof(saddr));
	saddr.sin_family = AF_INET;
	saddr.sin_port = htons(6000);
	saddr.sin_addr.s_addr = inet_addr("127.0.0.1");

	int res = connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
	assert(res != -1);
	while(1)
	{
		printf("input:\n");
		char buff[128] = {0};
		fgets(buff,128,stdin);
		if(strncmp(buff,"end",3)==0)
		{
			break;
		}
		send(sockfd,buff,strlen(buff),0);
		memset(buff,0,128);
		recv(sockfd,buff,127,0);
		printf("buff=%s\n",buff);
	}
	close(sockfd);
}

UDP编程
服务器端

#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
int main()
{
	int sockfd = socket(AF_INET,SOCK_DGRAM,0);//创建监听套接字
	assert(sockfd != -1);
	struct sockaddr saddr,caddr;
	memset(&saddr,0,sizeof(saddr));
	saddr.sin_family = AF_INET;
	saddr.sin_port = htons(6000);
	saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
	int res = bind(sockfd,(struct saddr*)&saddr,sizeof(saddr));//绑定ip和port
	assert(res != -1);
	while(1)
	{
		char buff[128] = {0};
		int len = sizeof(caddr);
		recvfrom(sockfd,buff,127,0,(struct sockaddr*)&caddr,&len);
		printf("buff=%s\n,port:%d\n",buff,ntohs(caddr.sin_port));
		sendto(sockfd,"ok",2,0,(struct sockaddr*)&caddr,sizeof(caddr));
	}
	close(sockfd);
}

客户端

#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
int main()
{
	int sockfd = socket(AF_INET,SOCK_DGRAM,0);//创建监听套接字
	assert(sockfd != -1);
	struct sockaddr saddr;
	memset(&saddr,0,sizeof(saddr));
	saddr.sin_family = AF_INET;
	saddr.sin_port = htons(6000);
	saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
	while(1)
	{
		char buff[128] = {0};
		printf("input:\n");
		char buff[128] = {0};
		fgets(buff,128,stdin);
		if(strncmp(buff,"end",3)==0)
		{
			break;
		}
		sendto(sockfd,buff,strlen(buff),0,(struct sockaddr*)&saddr,sizeof(saddr));
		memset(buff,0,128);
		int len = sizeof(saddr);
		recvfrom(sockfd,buff,127,0,(struct sockaddr*)&saddr,&len);
		printf("buff=%s\n",buff);
	}
	close(sockfd);
}

TCP与UDP基本区别
1.TCP是面向连接的,而UDP是无连接的,即发送数据之前不需要建立连接
2.TCP提供可靠的服务。通过TCP连接传送的数据,无差错,不丢失,不重复,且按顺序到达,UDP尽最大努力交付,不保证可靠交付。
3.TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的,UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如视频会议)
4.每一天TCP连接只能是点到点的,UDP支持一对一,一对多,多对一和多对多的交互通信。
5.TCP首部开销20字节,UDP的首部开销小,只有8个字节
6.TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道
7.TCP有应答确认,超时重传机制,乱序会重排,会丢弃重复报文
UDP应用场景:
1.面向数据报方式
2.网络数据大多为短消息
3.拥有大量Client
4.对数据安全性无特殊要求
5.网络负担非常重,但对响应速度要求高

具体编程实时的区别
1.socket()的参数不同
2.UDP Server不需要调用listen和accept
3.UDP收发数据用recvfrom/sendto
4.TCP:地址信息在connect/accept时确定
5.UDP:在sendto/recvfrom函数中每次需要指定地址信息

编程区别
通常我们在说到网络编程时默认是指TCP编程,即用socket函数创建一个socket用于TCP通讯,即socket(AF_INET,SOCK_STREAM,0),这表示建立一个socket用于流式网络通讯。
SOCK_STREAM这种服务是面向连接的,即每次收发数据之前必须通过connect建立连接,也是双向的,即任何一方都可以收发数据,协议本身提供了一些保障机制保证它是可靠的、有序的,即每个包按照发送的顺序到达接收方。
而SOCK_DGRAM是数据服务,它是无连接的、不可靠的,因为通讯双方发送数据后不知道对方是否已经收到数据,是否正常收到数据。任何一方建立一个socket以后就可以用sendto发送数据,也可以用recvfrom接收数据。根本不关心对方是否存在,是否发送了数据。他的特点是通讯速度比较快。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值