诚意
诚意如你,当一诚的态度对待

导航

 

1     网络软件

客户端:c/s架构 ,  client/server

浏览器:BS架构  , brower/server

2     基于socket模块实现网络通信

socket参数的详解

socket.socket(family=AF_INET,type=SOCK_STREAM,proto=0,fileno=None)
创建socket对象的参数说明:

 

family 地址系列应为AF_INET(默认值),AF_INET6,AF_UNIX,AF_CAN或AF_RDS。
(AF_UNIX 域实际上是使用本地 socket 文件来通信)
type 套接字类型应为SOCK_STREAM(默认值),SOCK_DGRAM,SOCK_RAW或其他SOCK_常量之一。
SOCK_STREAM 是基于TCP的,有保障的(即能保证数据正确传送到对方)面向连接的SOCKET,多用于资料传送。 
SOCK_DGRAM 是基于UDP的,无保障的面向消息的socket,多用于在网络上发广播信息。
proto 协议号通常为零,可以省略,或者在地址族为AF_CAN的情况下,协议应为CAN_RAW或CAN_BCM之一。
fileno 如果指定了fileno,则其他参数将被忽略,导致带有指定文件描述符的套接字返回。
与socket.fromfd()不同,fileno将返回相同的套接字,而不是重复的。
这可能有助于使用socket.close()关闭一个独立的插座。

 

TCP(Transmission Control Protocol)可靠的、面向连接的协议(eg:打电话)、传输效率低全双工通信(发送缓存&接收缓存)、面向字节流。使用TCP的应用:Web浏览器;电子邮件、文件传输程序。

UDP(User Datagram Protocol)不可靠的、无连接的服务,传输效率高(发送前时延小),一对一、一对多、多对一、多对多、面向报文,尽最大努力服务,无拥塞控制。使用UDP的应用:域名系统 (DNS);视频流;IP语音(VoIP)。

 

 

服务端套接字函数
s.bind()    绑定(主机,端口号)到套接字
s.listen()  开始TCP监听
s.accept()  被动接受TCP客户的连接,(阻塞式)等待连接的到来

客户端套接字函数
s.connect()     主动初始化TCP服务器连接
s.connect_ex()  connect()函数的扩展版本,出错时返回出错码,而不是抛出异常

公共用途的套接字函数
s.recv()            接收TCP数据
s.send()            发送TCP数据(send在待发送数据量大于己端缓存区剩余空间时,数据丢失,不会发完)
s.sendall()         发送完整的TCP数据(本质就是循环调用send,sendall在待发送数据量大于己端缓存区剩余空间时,数据不丢失,循环调用send直到发完)
s.recvfrom()        接收UDP数据
s.sendto()          发送UDP数据
s.getpeername()     连接到当前套接字的远端的地址
s.getsockname()     当前套接字的地址
s.getsockopt()      返回指定套接字的参数
s.setsockopt()      设置指定套接字的参数
s.close()           关闭套接字

面向锁的套接字方法
s.setblocking()     设置套接字的阻塞与非阻塞模式
s.settimeout()      设置阻塞套接字操作的超时时间
s.gettimeout()      得到阻塞套接字操作的超时时间

面向文件的套接字的函数
s.fileno()          套接字的文件描述符
s.makefile()        创建一个与该套接字相关的文件
View Code

 

服务端:

              accept,阻塞:等待客户端来连接。

              recv,  阻塞:等待客户端发来数据。

                           

客户端:

              connect,阻塞:一直在连接,直到连接成功才往下运行其他代码。

              recv,  阻塞:等待服务端发来数据。

2.1   案例1:基于TCP简单的连接通信

服务端:

 1 #创建服务端socket对象
 2 server = socket.socket()
 3 
 4 #绑定服务端IP和端口到套接字
 5 server.bind(('192.168.13.126',8000))
 6 
 7 #同时可访问5个
 8 server.listen(5)        #服务端等待连接的限制
 9 
10 #等待客户端来连接,如果不来,就一直等待
11 #addr是客户端的地址信息
12 #conn是客户端与服务的连接的介质(对象)  #这里的介质的意思是服务端与客户端相连的介质
#服务端accept接收的Conn(全双工管道)   是客户端传过来的socket对象
13 conn,addr = server.accept() #客户端与服务端建立连接 14 print(conn,addr) 15 16 # 通过对象(介质)获取客户端发送的消息 17 # 1024表示:服务端通过(伞)获取数据时,一次性最多拿1024字节 18 data = conn.recv(1024) 19 print(data) 20 21 # 服务端通过连接对象(伞)给客户端回复了一个消息。 22 conn.send(b'stop') 23 24 #与客户端断开连接 25 conn.close() 26 27 #关闭服务端的服务 28 server.close() 29 30

 

 

客户端:

 1 import  socket
 2 
 3   #创建客户端socket对象
 4 
 5   client = socket.socket()
 6 
 7   
 8 
 9   # 客户端向服务端发起连接请求
10 
11 # 阻塞,去连接,直到连接成功后才会继续向下走。
12 
13   client.connect(('192.168.13.126',8000))
14 
15   
16 
17   # # 链接上服务端后,向服务端发送消息
18 
19   client.send(b'hello')
20 
21   
22 
23   # 客户端等待服务端给他发送消息
24 
25   data = client.recv(1024)
26 
27   print(data)
28 
29   
30 
31   # 关闭自己
32 
33   client.close() 

 

2.2   案例2:基于TCP交互式循环单播

服务端:

 1 import  socket
 2 server = socket.socket()
 3 server.bind(('192.168.13.126',8001))
 4 
 5 server.listen(5)
 6 
 7 while True:       #服务器无限循环
 8     conn,addr = server.accept()
 9     while True:    #通讯循环
10         data = conn.recv(1024)
11         print(data.decode('utf-8'))
12         if data == b'exit':
13             break
14         data = input("回答:")
15         response = data
16         conn.send(response.encode('utf-8'))
17     conn.close()

 

 

客户端:

 1 import socket
 2 
 3 cli = socket.socket()
 4 
 5 cli.connect(('192.168.13.126',8001))
 6 
 7 while True:
 8     name = input("请输入姓名:")
 9     cli.send(name.encode('utf-8'))
10     if name == 'exit':
11         break
12     response = cli.recv(1024)
13     print(response.decode('utf-8'))
14 
15 cli.close() 

2.3 案例3:关于客户端单方面断开连接报错的问题

 1 import socket
 2 
 3 server  = socket.socket()
 4 IP_PORT = ('127.0.0.1',8899)
 5 server.bind(IP_PORT)
 6 server.listen(5)
 7 
 8 while 1:
 9     print("server is working......")
10     conn,addr = server.accept()
11     while 1:
12         try:        #针对Windows系统,当服务端与客户端连接时,客户端单方面断开连接,服务端就会报错
13             data = conn.recv(1024)
14             if len(data) == 0:  #针对Linux系统当服务端与客户端连接时,客户端单方面断开连接,服务端接受的数据就为空
15                 break
16             if data == b'exit':
17                 break
18             conn.send(b"hello")
19         except Exception as e:
20             break
21     conn.close()
服务端
 1 import  socket
 2 
 3 client = socket.socket()
 4 client.connect(('127.0.0.1',8899))
 5 
 6 while 1:
 7     s = input(">>>").encode('utf8')
 8     client.send(s)
 9 
10     p = client.recv(1024).decode('utf8')
11     print(p)
客户端

 

 

 

 

 

2.3   补充:

为什么要网络通信发送的是字节?而不是字符串?

                            py3, send/recv 都是字节(所谓字节,8位1字节)

                            py2, send/recv 都是字符串

python3中的字符串中是默认Unicode编码,所以需要转码压缩

python2中默认字符串就是ascii编码

 

 

 

 

posted on 2018-09-03 19:38  诚意  阅读(230)  评论(0)    收藏  举报