网络编程
从广义上讲,网络编程就是信息的发送和接收,中间传输就是物理线路的作用。
网络编程的主要任务是在发送端通过规定的协议将信息组装成数据包,并在接收端根据规定的协议解析数据包,提取相应的信息,达到通信的目的。中间最重要的是数据包的组装、数据包的过滤、数据包的捕获、数据包的分析,当然还有一些最后的处理,比如代码、开发工具、数据库、服务器设置,以及网页设计。
套接字是网络通信的关键。套接字也是应用程序和网络协议之间的接口。套接字由 IP 和端口号组成。
网络层通信主要由两种通信协议组成:TCP和UDP。数据传输的基本单位是数据包。网络层通信的关键是通过网络应用程序发送网络层协议封装的数据包,从而使计算机能够进行通信。
Socket
套接字是一个对象,它为特定网络协议(如 TCP/IP、ICMP/IP、UDP/IP 等)套件对上的网络应用程序提供者提供当前的可移植标准。它们允许程序接受并建立连接,例如发送和接收数据。为了建立通信通道,网络通信的每个端点都拥有一个套接字对象是极其重要的。
Socket是应用层和TCP/IP协议族之间进行通信的中间软件抽象层。它是一组接口。在设计模式上,Socket实际上是一种门面模式,将复杂的TCP/IP协议族隐藏在Socket接口的背后。对于用户来说,一组简单的接口就够了,让Socket组织数据来满足指定的需求。协议。因此,我们不需要深入了解TCP/UDP协议。套接字已经为我们封装好了。我们只需要按照socket的规定来编程即可。我们写的程序自然会遵循TCP/UDP标准。
一般socket建立链接需要六个步骤,其中包括:socket.socket()创建socket对象、s.bind绑定地址到socket对象、s.listen监听地址端口、s.accept阻塞接受链接请求、s.send,s.recv方法处理通信数据、s.close关闭链接。
python scoket
Python 提供了两种级别的网络服务访问:
低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统 Socket 接口的全部方法。
高级别的网络服务模块 SocketServer, 它提供了服务器中心类,可以简化网络服务器的开发。
Python 中,我们用socket库的 socket()函数来创建套接字,语法格式如下:
socket.socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None)
参数:
socket.socket(socket.AF_INET,socket.SOCK_STREAM)
使用给定的地址族,套接字类型和协议号来创建一个新套接字。
family
为指定的地址族:
socket.AF_UNIX
:只能够用于单一的Unix系统进程间通信
socket.AF_INET
:服务器之间的网络通信(ipv4协议的TCP和UDP)ipv4,默认为这个
socket.AF_INET6
:服务器之间的网络通信ipv6
type
为指定的套接字类型:
socket.SOCK_STREAM
:面向连接的TCP,默认为这个
socket.SOCK_DGRAM
:面向非连接的UDP
套接字API
socket.scoket(…)可以创建一个scoket对象,socket对象只是一个TCP或UDP数据包的装载对象,主机通过该对象发送数据包。因此通讯的双方都需要socket对象。一方作为数据的接收端服务端,一方作为数据的发送端客户端。socket对象提供了API来创建服务端和客户端程序。
方法 | 描述 |
---|---|
服务器API | 服务器端套接字 |
套接字.bind() | 将地址(主机、端口)绑定到套接字。在AF_INET下,地址以元组(主机,端口)的形式表示。用于服务器,绑定监听端口,可以使用0.0.0.0接收所有IP,127.0.0.0只接受本地服务。 |
套接字.listen() | 启动 TCP 监听。该参数指定操作系统在拒绝连接之前可以挂起的最大连接数。该值必须至少为1,大多数应用程序可以设置为5,这是服务器端程序。 |
套接字.accept() | 被动接受TCP客户端连接,(阻塞式)等待连接的到来,没有来自客户端的请求是处于阻塞状态。accept方法会返回一个含有两个元素的元组,(fd,addr)fd, addr = self._accept() 。第一个元素是新的socket对象,服务器通过它与客户端通信。第二个元素是客户端的地址及端口信息。 |
客户端API | 客户端套接字 |
套接字.connect() | 主动初始化TCP服务器连接。参数格式是一个元组(主机名,端口)。如果发生连接错误,则返回socket.error错误。元组的第一个参数是ip,可以是ip,也可以是域名。第一个数字是端口号,即套接字。 |
套接字.connect_ex() | connect() 函数的扩展版本,在发生错误时返回错误代码而不是引发异常。 |
公共API | 公用套接字函数 |
套接字.recv() | 接收TCP数据。数据以字符串的形式返回。有两个参数。 bufsize 指定要接收的最大数据量。 flag 提供有关消息的附加信息,通常可以忽略。 |
套接字.send() | 发送 TCP 数据,将参数作为封装的 TCP 数据包发送到连接的套接字。返回值是要发送的字节数。参数只能是字节。其他类型是高级语言所特有的,无法被计算机解析。只有将其他类型转换为字节编码('utf-8')才能发送。 |
套接字.sendall() | 完整发送TCP数据,完整发送TCP数据。将字符串中的数据发送到连接的套接字,但在返回之前尝试发送所有数据。成功时返回 None,失败时抛出异常。 |
socket.recvfrom() | 接收UDP数据,与recv()类似,但返回值为(data,address)。其中data是包含接收到的数据的字符串,address是数据发送到的套接字地址。创建套接字时类型参数必须对应。 |
套接字.sendto() | 将 UDP 数据发送到套接字,其中地址是指定远程地址的 (ipaddr, port) 形式的元组。返回值是发送的字节数。 |
套接字.close() | 关闭套接字 |
套接字.getpeername() | 返回连接套接字的远程地址。返回值通常是一个元组(ipaddr,端口) |
socket.getsockname() | 返回套接字自己的地址。通常是一个元组(ipaddr,端口) |
socket.setsockopt(级别,optname,值) | 设置给定套接字选项的值 |
socket.getsockopt(级别,optname[.buflen]) | 返回套接字选项的值。 |
socket.settimeout(超时) | 设置socket操作的超时时间。超时是一个以秒为单位的浮点数。 None 值表示没有超时时间。一般来说,超时应该在第一次创建套接字时设置,因为它们可能用于连接操作(例如 connect()) |
套接字.gettimeout() | 返回当前超时时间的值(以秒为单位)。如果没有设置超时时间,则返回None。 |
套接字.fileno() | 返回套接字的文件描述符 |
socket.setblocking(标志) | 如果flag为0,则将套接字设置为非阻塞模式,否则将套接字设置为阻塞模式(默认)。在非阻塞模式下,如果调用recv()没有找到数据,或者调用send()无法立即发送数据,则会引发socket.error异常。 |
套接字.makefile() | 创建与套接字关联的文件 |
简单TCP案例
服务端:
import socket
# 创建socket,网络协议为ipv4,网络层协议为TCP
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定套接字,接收所有ip
s.bind(('0.0.0.0',9000))
# 监听端口,指定连接最大数量
s.listen(2)
print("is listening...")
# 等待客户端连接,返回服务端scoket连接和套接字
fd, addr = s.accept()
print("connect to client successful")
# 接收客户端数据
data = fd.recv(1024)
print(data)
# 响应客户端
fd.send("Welcome to connect !".encode("utf-8"))
# 关闭连接
s.close()
print("closed")
客户:
import socket
# 创建socket
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 建立连接
s.connect(("127.0.0.1",9000))
# 发送数据
s.send("hello".encode("utf-8"))
print("connect to server successful")
# 接收响应数据
data = s.recv(1024)
print(data.decode("utf-8"))
# 关闭连接
s.close()
print("closed")
TCP协议的
三次握手
建立连接,所以第一次必须由客户端发送连接请求,因此服务端必须要在客户端先开启服务。
服务端运行结果:
客户端运行结果:
python聊天室
服务器端程序
import socket
s = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
s.bind(('0.0.0.0', 9000))
s.listen(1)
print("is listening...")
fd, addr = s.accept()
print(fd.getpeername(), "is connected")
fd.send("welcome to connect !".encode('utf-8'))
def send_msg():
print("请输入:")
data0 = input()
fd.send(data0.encode("utf-8"))
def recv_meg():
data1 = fd.recv(1024)
print("收到客户端消息:", data1)
if __name__ == "__main__":
while True:
# 接收消息
recv_meg()
# 发送消息
send_msg()
print("已发送")
客户程序
import socket
s = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
s.connect(('127.0.0.1', 9000))
print("连接成功!")
def make_sock():
send_data=input()
s.send(send_data.encode("utf-8"))
print("已发送!")
return None
def recv_scok():
get_data = s.recv(1024)
if get_data is None:
print("未收到数据")
else:
print("收到服务端内容:")
print(get_data)
return None
if __name__ == "__main__":
flag = 1
while True:
if flag == 0:
s.close()
break
else:
print("请输入:")
make_sock()
# 接收消息
recv_scok()
print("请选择:任意.继续聊天 0.退出")
a = input()
flag = a
参考资料:
https://www.cnblogs.com/yunlong-study/p/9283529.html
https://www.cnblogs.com/zhangyingai/p/7097922.html
https://www.cnblogs.com/zhangxinqi/p/8243919.html
http://www.runoob.com/python3/python3-socket.html
UDP协议
udp和tcp差不多,只是udp使无连接无状态的,不需要监听,只有接收和发送数据。可能造成数据丢失。
# 客户端
import socket
s = socket.socket(family=socket.AF_INET,type=socket.SOCK_DGRAM)
# 发送数据
s.sendto("hell0".encode("utf-8"),('127.0.0.1',9000))
# 接收数据
data = s.recv(1024)
print(data)
if __name__ == "__main__":
while True:
print("请输入:")
put = input()
s.sendto(put.encode("utf-8"),('127.0.0.1',9000))
print("收到服务端的数据:",s.recvfrom(1024))
# 服务器端
import socket
s = socket.socket(family=socket.AF_INET,type=socket.SOCK_DGRAM)
# 绑定端口
s.bind(("127.0.0.1",9000))
# 接收数据
data = s.recvfrom(1024)
print("收到来自客户端消息:",data)
# 发送数据
s.sendto("send a message to you".encode("utf-8"),('127.0.0.1',9000))
if __name__ == "__main__":
while True:
print("请输入:")
put = input()
s.sendto(put.encode("utf-8"),('127.0.0.1',9000))
print("收到客户端的数据:",s.recvfrom(1024))
udp协议程序只管发送和接收数据,如果接收端没有udp程序接收数据就丢失了。
在主机上测试,发送端是自己,接收端也是省内,客户端的Qi激活,数据全部在服务器上。