对于TCP/udp的说明已经不少了,我在这里只是简单的说明一下python
套接字是一种具备以前所说的“通讯端点”概念的计算网络数据结构。至关
于电话插口,没它没法通讯,这个比喻很是形象。
套接字起源于20世纪70年代加州伯克利分校版本的Unix,即BSD Unix
。又称为“伯克利套接字”或“BSD套接字”。最初套接字被设计用在同一台
主机上多个应用程序之间的通信,这被称为进程间通信或IPC。
套接字分两种:基于文件型和基于网络的
第一个套接字家族为AF_UNIX,表示“地址家族:UNIX”。包括
Python在内的大多数流行平台上都使用术语“地址家族”及其缩写AF。因为两
个进程都运行在同一台机器上,并且这些套接字是基于文件的,因此它们的底
层结构是由文件系统来支持的。能够理解为同一台电脑上,文件系统确实是不
同的进程都能进行访问的。
第二个套接字家族为AF_INET,表示”地址家族:Internet“。还有
一种地址家族AF_INET6被用于网际协议IPv6寻址。Python 2.5中加入了一种
Linux套接字的支持:AF_NETLINK(无链接)套接字家族,让用户代码与内核
代码之间的IPC可使用标准BSD套接字接口,这种方法更为精巧和安全。
Python只支持AF_UNIX、AF_NETLINK和AF_INET家族。网络编程关注
AF_INET。
若是把套接字比做电话的查看——即通讯的最底层结构,那主机与端
口就至关于区号和电话号码的一对组合。一个因特网地址由网络通讯必须的主
机与端口组成。
并且另外一端必定要有人接听才行,不然会提示”对不起,您拨打的电
话是空号,请查询后再拨“。一样你也可能会遇到如”不能链接该服务器、服
务器没法响应“等。合法的端口范围是0~65535,其中小于1024端口号为系统
保留端口。编程
面向链接:通讯以前必定要创建一条链接,这种通讯方式也被成为”虚电路
“或”流套接字“。面向链接的通讯方式提供了顺序的、可靠地、不会重复的
数据传输,并且也不会被加上数据边界。这意味着,每发送一份信息,可能会
被拆分红多份,每份都会很少很多地正确到达目的地,而后从新按顺序拼装起
来,传给正等待的应用程序。
实现这种链接的主要协议就是传输控制协议TCP。要建立TCP套接字就
得建立时指定套接字类型为SOCK_STREAM。TCP套接字这个类型表示它做为流套
接字的特色。因为这些套接字使用网际协议IP来查找网络中的主机,因此这样
造成的整个系统,通常会由这两个协议(TCP和IP)组合描述,即TCP/IP。
无链接:无需创建链接就能够通信。但此时,数据到达的顺序、可靠
性及不重复性就没法保障了。数据报会保留数据边界,这就表示数据是整个发
送的,不会像面向链接的协议先拆分红小块。它就至关于邮政服务同样,邮件
和包裹不必定按照发送顺序达到,有的甚至可能根本到达不到。并且网络中的
报文可能会重复发送。
那么这么多缺点,为何还要使用它呢?因为面向链接套接字要提供
一些保证,须要维护虚电路链接,这都是严重的额外负担。数据报没有这些负
担,全部它会更”便宜“,一般能提供更好的性能,更适合某些场合,如现场
直播要求的实时数据讲究快等。
实现这种链接的主要协议是用户数据报协议UDP。要建立UDP套接字就
得建立时指定套接字类型为SOCK_DGRAM。这个名字源于datagram(数据报),
这些套接字使用网际协议来查找网络主机,整个系统叫UDP/IP。 安全
使用socket模块的socket()函数来建立套接字。语法以下:
socket(socket_family, socket_type, protocol=0)
其中socket_family不是AF_VNIX就是AF_INET,socket_type能够是
SOCK_STREAM或者SOCK_DGRAM,protocol通常不填,默认值是0。
建立一个TCP/IP套接字的语法以下:
tcpSock = socket.socket(socket.AF_INET,
socket.SOCK_STREAM)
一样建立一个UDP/IP套接字的语法以下:
udpSock = socket.socket(socket.AF_INET,
socket.SOCK_DGRAM)
因为socket模块中有太多属性,因此使用"from socket import *"语
句,把socket模块里面的全部属性都带到命名空间中,大幅缩短代码。调用如
下:
tcpSock = socket(AF_INET, SOCK_STREAM)服务器
下面是最经常使用的套接字对象方法:
服务器端套接字函数网络
socket类型数据结构 |
描述socket |
s.bind()tcp |
绑定地址(主机号 端口号对)到套接字函数 |
s.listen()性能 |
开始TCP监听 |
s.accept() |
被动接受TCP客户端链接,(阻塞式)等待连续的到来 |
客户端套接字函数
socket类型 |
描述 |
s.connect() |
主动初始化TCP服务器链接 |
s.connect_ex() |
connect()函数扩展版本,出错时返回出错码而不是跑出异常 |
公共用途的套接字函数
socket类型 |
描述 |
s.recv() |
接受TCP数据 |
s.send() |
发送TCP数据 |
s.sendall() |
完整发送TCP数据 |
s.recvfrom() |
接受UDP数据 |
s.sendto() |
发送UDP数据 |
s.getpeername() |
链接到当前套接字的远端地址(TCP链接) |
s.getsockname() |
获取当前套接字的地址 |
s.getsockopt() |
返回指定套接字的参数 |
s.setsockopt() |
设置指定套接字的参数 |
s.close() |
关闭套接字 |
面向模块的套接字函数
socket类型 |
描述 |
s.setblocking() |
设置套接字的阻塞与非阻塞模式 |
s.settimeout() |
设置阻塞套接字操做的超时时间 |
s.gettimeout() |
获得阻塞套接字操做的超时时间 |
面向文件的套接字函数
socket类型 |
描述 |
s.fileno() |
套接字的文件描述符 |
s.makefile() |
建立一个与套接字关联的文件对象 |
TCP服务端代码
#! /usr/bin/env python #coding=utf-8 import socket bind_ip = "" bind_port = 9999 server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) server.bind((bind_ip,bind_port)) server.listen(5) try: while True: client,add = server.accept() print "[*]你监听的是:%s:%d" % (add[0],add[1]) while True: data = client.recv(1024) if not data: break print data data = raw_input('> ') client.send(data) # print data else: client.close() except Exception as e: print e server.close()
TCP客户端代码
#! /usr/bin/env python #coding=utf-8 import socket target_host = "127.0.0.1" target_port = 9999 #创建一个socket对象 client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #连接客户端 client.connect((target_host,target_port)) while True: data = raw_input('> ') client.send(data) #发送一些数据 #client.send("GET /HTTP/1.1\r\nHost:baidu.com\r\n\r\n") data = client.recv(4096) if not data: break print data
UDP服务端
# -*- coding: utf-8 -*- from socket import * from time import ctime HOST = '' #主机名 PORT = 21567 #端口号 BUFSIZE = 1024 #缓冲区大小1K ADDR = (HOST,PORT) udpSerSock = socket(AF_INET, SOCK_DGRAM) udpSerSock.bind(ADDR) #绑定地址到套接字 while True: #无限循环等待链接到来 try: print 'Waiting for message ....' data, addr = udpSerSock.recvfrom(BUFSIZE) #接受UDP print 'Get client msg is: ', data udpSerSock.sendto('[%s] %s' %(ctime(),data), addr) #发送UDP print 'Received from and returned to: ',addr except Exception,e: print 'Error: ',e udpSerSock.close() #关闭服务器
UDP服务端
# -*- coding: utf-8 -*- from socket import * HOST = 'localhost' #主机名 PORT = 21567 #端口号 与服务器一致 BUFSIZE = 1024 #缓冲区大小1K ADDR = (HOST,PORT) udpCliSock = socket(AF_INET, SOCK_DGRAM) while True: #无限循环等待链接到来 try: data = raw_input('>') if not data: break udpCliSock.sendto(data, ADDR) #发送数据 data,ADDR = udpCliSock.recvfrom(BUFSIZE) #接受数据 if not data: break print 'Server : ', data except Exception,e: print 'Error: ',e udpCliSock.close() #关闭客户端