1、网络基础编程
在学习网络编程前,要对网络通讯的五层协议有所了解,那什么是协议呢,协议就是各方规定遵照的一种标准。缓存
网络通讯就像寄信件,是信息与数据的交换,而在生活中咱们寄信件,信件也不是从咱们手里瞬间到收件人手里,每一次信件通讯,都会经历这样几个固定流程:写信、装信封、投到邮箱、邮局取件、运输到目的地邮局、目的地邮局根据详细地址派送、收件人收件、拆信封、读信。服务器
网络通讯也是一样的道理,数据的传输总有必定的流程:发送端程序将数据打包,给数据包印上目标地址,将数据包交给网关,经过路由转发到达目的网络,目的网络网关在根据详细地址分发、目的主机接收数据、拆包、读数据。网络
这中间咱们按照每部分负责的任务的不一样,将整个通讯划分为五层(分法不惟一,这是最易理解的一种),由下到上分别是物理层、数据链路层、网络层、运输层、应用层,每一层都将较下的一层彻底封装,消除通讯双方软硬件的差异,而每一层又有约定好的规则以和对方通讯,咱们这篇文章所要讲的,就是发生在运输层的通讯。socket
咱们先来思考一个问题:一台主机的一个进程发送数据时,是如何标识它是发送给目标主机的哪一个进程呢?目标主机接受到数据时,由如何判断这份数据是发送给本机的哪一个进程呢?tcp
这就是运输层的任务,也就是说,运输层负责两个主机中的应用进程之间的通讯。那么上面的问题究竟是怎么解决的呢?这就要提到一个新的概念:套接字。学习
套接字的概念很简单,每台主机有一个惟一的主机地址标识,同时主机内还有标识本身进程的序号id,称做端口,将这两个标识符结合就构成了一个套接字(socket),这个套接字能惟一标识网络中的一个进程。接下来咱们的网络编程,都是围绕这个套接字展开的。spa
运输层的协议主要有UDP和TCP协议,这两个协议都是为了解决进程通讯,它们的区别主要是这几点:UDP是无链接、不可靠协议,TCP是有链接、可靠协议,链接指的是通讯前要创建链接(链接提供了许多功能:确认、流量控制、链接管理等),可靠指的是若是数据未抵达有对应处理(不可靠则指只负责发送数据)。code
这样就了解的差很少了,固然,关于运输层的技术还有不少,难点重点都没有提到,有兴趣的同窗能够本身再学习。orm
2、通讯模式
对咱们来讲,进行网络通讯的目的是为了获取信息,而互联网上的信息需求者远远多于信息提供者,不止如此,信息的提供者必须24小时当即回复需求者的请求,这样就产生了客户服务器模式。客户服务器模式是一个逻辑概念,它将主机分为两类,等待请求的是服务器端、发起请求的是客户端,因此服务器端的套接字是必须是公开的,客户端的套接字能够在请求时给服务器端。
3、实现
对UDP来讲:由于不须要创建链接,因此只须要在两台主机上各构造一个socket,就能直接发送和接收数据了。
对TCP来讲:首先须要创建链接,一个链接就是一对手动绑定的socket,链接成功后就能收发数据了。
结合客户服务端模式,对同一种协议,socket的构造方法也按客户端和服务器分为两种。
话很少说,上代码!
这是基于TCP协议的:
#socket_server_tcp # import socket from socket import * ip_port=('127.0.0.1',8080) back_log=5 buffer_size=1024 tcp_server=socket(AF_INET,SOCK_STREAM) tcp_server.bind(ip_port) tcp_server.listen(back_log) while True: print('服务端开始运行了') conn,addr=tcp_server.accept() #服务端阻塞 print('双向连接是',conn) print('客户端地址',addr) while True: try: data=conn.recv(buffer_size) print('客户端发来的消息是',data.decode('utf-8')) conn.send(data.upper()) except Exception: break conn.close() tcp_server.close()
#socket_client_tcp # import socket from socket import * ip_port=('127.0.0.1',8080) back_log=5 buffer_size=1024 tcp_client=socket(AF_INET,SOCK_STREAM) tcp_client.connect(ip_port) while True: msg=input('>>: ').strip() if not msg:continue tcp_client.send(msg.encode('utf-8')) print('客户端已经发送消息') data=tcp_client.recv(buffer_size) print('收到服务端发来的消息',data.decode('utf-8')) tcp_client.close()
接下来是基于UDP协议的:
# socket_server_udp from socket import * ip_port=('127.0.0.1',8080) buffer_size=1024 udp_server=socket(AF_INET,SOCK_DGRAM) #数据报 udp_server.bind(ip_port) while True: data,addr=udp_server.recvfrom(buffer_size) print('收到来自{}的消息:{}'.format(addr, data)) udp_server.sendto(data.upper(),addr)
# socket_client_udp from socket import * ip_port=('127.0.0.1',8080) buffer_size=1024 udp_client=socket(AF_INET,SOCK_DGRAM) #数据报 while True: msg=input('>>: ').strip() udp_client.sendto(msg.encode('utf-8'),ip_port) data,addr=udp_client.recvfrom(buffer_size) # print(data.decode('utf-8')) print('收到服务端发来的消息', data)
运行下试试!
这两对代码已经能实现基本的功能,但还有许多功能没有实现,如TCP版不能同时链接多用户,粘包问题(一次接收的数据若是大于缓存区大小就会把剩下的内容附加到下次接受的开头),这些咱们放到下次来说。