您的位置:首页 > 理论基础 > 计算机网络

python学习笔记(2)网络编程

2016-10-22 16:03 633 查看

套接字

套接字是计算机网络数据结构,网络应用程序必须创建套接字,没有套接字就无法进行网络通信。套接字最初出现在伯克利版本unix(BSD unix)中,是为了实现进程间的通讯。有两种类型的套接字,基于文件的和基于网络的,因为两个进程是在同一个计算机上的,所以这些套接字是基于文件的AF_LOCAL(AF_UNIX是AF_LOCAL的前身,python中任然在使用AF_UNIX)。不同主机间的通讯是基于网络的套接字AF_INET,(AF_INET6是基于IPv6寻址的版本)。python等大多数受欢迎的平台上都使用术语地址家族AF,但一些比较旧的系统可能会用协议家族PF。

套接字地址:主机-端口对

   一个网络地址由主机地址和端口号组成,有效的端口号地址是0-65535(0-1024端口号预留给系统),在POSIX兼容系统中,可以在/etc/services中找到预留的端口号列表(服务器/协议和套接字类型)。
  如下图:21号端口是tp服务,22号端口是ssh服务,23号端口是telnet服务



也可以在此网站中查看众所周知的服务端口号列表:http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml


面向连接的套接字和无连接的套接字

       不管采用哪种地址家族,都会有两种不同的套接字连接,面向连接的套接字(虚拟电路或流套接字)和无连接的套接字。面向连接的通信提供序列化的,可靠的和不重复的数据交付,但是没有边界记录,这种方式将数据差分成多个片段,确保每个片段都能够到达目的地,然后按顺序拼在一起,传递给应用程序。它是基于传输控制协议(TCP)实现的,为了创建TCP 套接字,必须使用SOCK_STREAM作为套接字类型。无连接的套接字(数据报类型套接字)它在通信开始之前并不需要建立连接,它无法保证顺序性,可靠性和重复性,但是它会记录边界信息,也就是信息是以整体的形式发送的而不是切分成片段。它不能保证数据能够成功到达,而且为了将其添加到并发通信中(同时和多个对象通信),在网络中也可能存在重复消息。UDP套接字的套接字类型是SOCK_DGRAM(datagram数据报)。

python中的网络编程

 套接字模块名为socket,所以在python网络编程中要先导入socket模块。
 创建套接字:socke(socket_family,socket_type,protocol)
           其中socket_family是SOCKET_UNIX或SOCKET_IENT,socket_type是SOCKET_SRTEAM或SOCKET_DGRAM,protocol表示套接字协议,通常省略,默认为0。
常见的套接字内置方法和属性
服务器端:
s.bind(addr)                    //将主机名和端口号绑定到套接字上
s.listen(int)                   //设置并启动tcp监听器,参数为在连接被拒绝或转接之前,传入连接请求的最大数
s.accept()                      //被动接受tcp客户端连接,一直等待直到连接到达(阻塞)

客户端:
s.connect(addr)                  //连接到服务器
s.connect_ex()                   //connect 的扩展版本,此时会以错误码的形式返回问题,而不是抛出一个异常

普通的套接字方法:
s.recv()                         //接收tcp消息
s.recv_into()                    //接收tcp消息到指定的缓冲区
s.send()                         //发送tcp消息
s.sendall()                      //完整地发送tcp消息
s.recvfrom()                     //接收udp消息
s.recvfrom_into()                //接收udp消息到指定缓冲区
s.sendto()                       //发送udp消息
s.getpeername()                  //连接到套接字(tcp)的远程地址
s.getsockname()                  //当前套接字的地址
s.setsockopt()                   //返回给定套接字选项的值
s.setsockopt()                   //设置套接字选项的值
s.shotdown()                     //关闭连接
s.close()                        //关闭套接字

s.setblocking()                  //设置套接字的阻塞和非阻塞模式
s.makefile()                     //创建与套接字关联的文件对象


tcp套接字通信示例
server.py

__author__ = 'wenhai.dai'
from socket import *
import time
import threading
def tcplink(sock, addr):
print('Accept new connection from %s:%s...' % addr)
sock.send(b'Welcome!')
while True:
data = sock.recv(1024)
time.sleep(1)
if not data or data.decode('utf-8') == 'exit':
break
sock.send(('Hello, %s!' % data.decode('utf-8')).encode('utf-8'))
sock.close()
print('Connection from %s:%s closed.' % addr)
tcpserv = socket(AF_INET, SOCK_STREAM)
tcpserv.bind(('', 9999))
tcpserv.listen(5)
while True:
sock, addr = tcpserv.accept()
t = threading.Thread(target=tcplink, args=(sock, addr))
t.start()


Accept new connection from 127.0.0.1:65211...

Connection from 127.0.0.1:65211 closed.

client.py
__author__ = 'wenhai.dai'
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 9999))
print(s.recv(1024).decode('utf-8'))
for data in [b'Michael', b'Tracy', b'Sarah']:
s.send(data)
print(s.recv(1024).decode('utf-8'))
s.send(b'exit')
s.close()


Welcome!

Hello, Michael!

Hello, Tracy!

Hello, Sarah!

udp套接字通信示例

server.py

__author__ = 'wenhai.dai'
from socket import *
from time import ctime
s = socket(AF_INET, SOCK_DGRAM)
s.bind(('127.0.0.1', 12345))
while True:
print('waiting for message...')
data, addr = s.recvfrom(1024)
s.sendto(ctime().encode('utf-8'), addr)
if data.decode('utf-8') == 'exit':
break
print('receive from and return to :', addr)
s.close()
waiting for message...

receive from and return to : ('127.0.0.1', 63861)

waiting for message...

receive from and return to : ('127.0.0.1', 63861)

waiting for message...

receive from and return to : ('127.0.0.1', 63861)

waiting for message...

Process finished with exit code 0

client.py
__author__ = 'wenhai.dai'
from socket import *
c = socket(AF_INET, SOCK_DGRAM)
ADDR = ('127.0.0.1', 12345)
while True:
data = input('>>')
c.sendto(data.encode('utf-8'), ADDR)
if data == 'exit':
break
data, addr = c.recvfrom(1024)
if not data:
pass
else:
print(data.decode('utf-8'), data)
c.close()
>>dai

Sat Oct 22 20:50:21 2016 b'Sat Oct 22 20:50:21 2016'

>>wen

Sat Oct 22 20:50:27 2016 b'Sat Oct 22 20:50:27 2016'

>>hai

Sat Oct 22 20:50:29 2016 b'Sat Oct 22 20:50:29 2016'

>>exit

Process finished with exit code 0

UDP通信和TCP通信的主要实现上的区别是UDP服务端不需要调用listen()函数来进行端口监听,服务端向客户端发送信息时调用服务端套接字对象的sendto()函数,把目标地址写在函数的参数中,而TCP实现是服务器端套接字对象的accept()函数返回客户端的套接字对象和地址,向客户端发送信息是调用客户端套接字对象的send()函数。在客户端的区别是UDP方式客户端套接字对象不需要调用connect()函数,地址都是在数据的发送和接受时作为参数来传递的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  python