一,什么是网络编程?
所谓的网络编程就是,让在不同的电脑上的软件能够进行数据传递,即进程之间的通信
二,TCP/IP协议简介
为了把全世界的所有不同类型的计算机都连接起来,就必须规定一套全球通用的协议,为了实现互联网这个目标,互联网协议簇(InternetProtocolSuite)就是通用协议标准。因为互联网协议包含了上百种协议标准,但是最重要的两个协议是TCP和IP协议,所以,大家把互联网的协议简称TCP/IP协议。
TCP/IP根据网络功能将网络分为了四层:链路层,网络层,传输层,应用层。有什么用途呢,是为了规范网络数据传输。
三,端口
假如左边的陌陌要和右边的陌陌通信,是怎么实现的呢,首先左边的陌陌通过ip地址找到右边对应的一台电脑,但是电脑上有很多进程,那怎么确定就要发给陌陌这个进程呢,答案是通过端口号来找到陌陌这个进程的,因为每台电脑上的不同进程都会对应一个不同的端口号。就好像我要去朋友家里玩,首先我知道他的家在哪里。到了他家里的时候,有很多房间,有他妈妈的,弟弟的,所以我们要找到他自己的房间。这是的房间对应端口号,家里的地址对应电脑的ip地址。
问题又来了,既然端口号是为了区分不同的进程的,那为什么不用pid呢?每台电脑的不同进程也对应不同的pid啊?这是因为pid是不固定的,端口号是固定的,在一台的电脑上对应某个进程的pid是3520,在别的电脑上相同的进程的pid可能就是3529了,所以才要用端口号来重新区分进程用于不同电脑上的通信。
端口的分类:1.知名端口(0~1023) 2.动态端口(1024~65535)
知名端口如:80端口用于http服务,21端口用于ftp服务。
动态端口是用户可以自己分配的。
如何查看自己的端口:netstat -an
四,ip地址
用逻辑值来标记一台电脑,如用192.168.1.100来标记这一台电脑。这个逻辑值就是ip地址。
五,UDP编程
UDP通信过程模型:
udp编程客户端:
客户端首先要声明一个UDPsocket,声明之后才能用send发消息,但为了要准确发送到目标主机,send时候要加上目的主机的ip和端口号。
import socket
#构建UDP协议的socket对象
udpSocket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
data = input('>>').strip()
udpSocket.sendto(data.encode('utf-8'),('localhost',8080))
udpSocket.close()
udp编程服务端:
作为接收端,由于对方要发消息过来,接收端肯定要固定一个端口号,并且udpSocket要邦定这个端口。如果没有固定的端口的话。那么发送方如果将消息发送到8888端口来,但是接收到的端口却不明确,所以不能发过来。只有当接收方将8888端口作为接收消息的端口,才能一直保持联系。邦定端口之后,就可以用recvfrom接收消息了。
import socket
udpSocket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
udpSocket.bind(('',8080)) #一般写'',表示邦定本机的任何一个ip
data = udpSocket.recvfrom(1024)
print(data)
服务端显示结果:
#(b'das', ('127.0.0.1', 53243))
六,UDP编程综合练习:一个简易聊天室
import socket
import threading
class WeChat(object):
def __init__(self):
self.udpSocket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
self.ip = '192.168.1.105'
self.port = '8080'
def sendData(self):
'''发送消息'''
while True:
data = input('\r<<')
#发消息的时候必须编码为字节型数据。由于对方主机接收软件是gb2312解码的,所以这里要编码成gb2312.
self.udpSocket.sendto(data.encode('gb2312'),(self.ip,int(self.port)))
def recvData(self):
'''接收消息'''
while True:
info = self.udpSocket.recvfrom(1024)
print('\r>>[%s]:%s'%(str(info[1]),info[0].decode('gb2312')))
def start(self):
self.udpSocket.bind(('',9999))
#开启两个线程,接收和发送消息同时进行。
ts = threading.Thread(target=self.sendData)
tr = threading.Thread(target=self.recvData)
ts.start()
tr.start()
ts.join()
tr.join()
if __name__ == '__main__':
wechat = WeChat()
wechat.start()
七,UDP广播
什么是UDP广播?就是基于UDP协议的广播。例如,你发送一个广播,你所在同一个网段内的主机都可以接收到数据。原理是,首先广播端将这一份信息发送给了交换机,交换机再将信息发送给在每个都连上此交换机的主机上。
from socket import *
#写要发送的目的地。写'<broadcast>'可以,写成你所在网段的网络广播地址也行。如写‘192.168.1.255’
dest = ('<broadcast>',8080)
#创建udp套接字
s = socket(AF_INET,SOCK_DGRAM)
#对这个需要发送数据的套接字进行修改设置,否则不能发送广播。
s.setsockopt(SOL_SOCKET,SO_BROADCAST,1)
s.sendto(b'haha',dest)
while True:
data, addr = s.recvfrom(1024)
print('received from %s:%s'%(addr,data))
s.close()