什么是socket
网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,可以用来实现不同虚拟机或不同计算机之间的通信。在Internet上的主机一般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。
Socket的英文原义是“孔”或“插座”。Socket正如其英文原意那样,像一个多孔插座。一台主机犹如布满各种插座的房间,每个插座有一个编号,有的插座提供220伏交流电, 有的提供110伏交流电,有的则提供有线电视节目。 客户软件将插头插到不同编号的插座,就可以得到不同的服务。
我知道上面那段话很枯燥,那就忘记吧!我们只需要记得:两个程序通过“网络”交互数据就使用socket,它只负责两件事:建立连接,传递数据。不能再简练了!!!
如何执行一段socket代码?
首先,我们先看下面这个例子,什么都不需要懂,我们只知道这么写就可以实现一个socket,让两个程序互相传递消息:
server: client:
先说一下它们是怎么跑起来的,新建两个python文件:socket_server.py,socket_client.py 分别将demo1_server Code和demo1_client Code中的代码粘到对应的文件中,先执行socket_server.py,再执行socket_client.py,就可以看到效果啦!代码拿去,先体验一下socket的效果。
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 __author__ = 'Eva_J' 4 import socket 5 6 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 7 sock.bind(('127.0.0.1',8001)) 8 sock.listen(5) 9 10 while True: 11 print 'waiting....' 12 connection, address = sock.accept() 13 receive = connection.recv(1024) 14 print 'receive the message from client:',receive 15 connection.send("received") 16 connection.close()
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 __author__ = 'Eva_J' 4 import socket 5 6 obj_client = socket.socket() 7 obj_client.connect(('127.0.0.1',8001)) 8 obj_client.send('help') 9 server_data = obj_client.recv(1024) 10 print server_data 11 obj_client.close()
一分钟拥有一个自己的socket程序!
执行成功了么?我们先不解释原理,一切以能把socket用起来为前提,把上面这段代码当做实现socket的模板代码,来看看哪些东西是我们可以替换的,先拼凑一个属于自己的socket程序。
server: client:
我们先从打印出来的内容来看,server端接收到了从client端发送过来的信息 'help' 。并且给client端发送了一条确认信息 'received',我们在client端接收到了这条信息。这就是数据交互的过程。send是发消息方法,recv是接收消息方法。我们只需要修改send和recv中的内容,就可以实现两个程序的数据交互了。
socket的实现就像是快递员取快递的过程,寄出包裹的是server端,快递员是client端,send和recv中的内容就是我们要寄出的东西,那么准备好了要寄出的东西,我们要告诉快递员到哪里来取件,看server中的sock.bind方法,这里面传了一个元组('ip','port')给bind方法,就是把包裹放在这个地址的这个端口等待快递员;而client端的obj_client.connect方法是告诉快递员,去那个地址找这个端口去取包裹。所以这个元组中的ip和port内容必须一致,是我和快递员约好的。我send的内容无所谓是什么,我send什么,客户端就recv什么,因为我要寄什么,快递员拿到的就是什么,他没有权利左右我寄什么东西。现在就行动起来,把要寄的东西和放东西的地址换成你自己的,来get一个属于自己的socket程序吧。
socket程序代码详解:
server: client:
创建socket对象——参数详解:
参数一:地址簇
socket.AF_INET IPv4(默认)
socket.AF_INET6 IPv6
socket.AF_UNIX 只能够用于单一的Unix系统进程间通信
参数二:类型
socket.SOCK_STREAM 流式socket , for TCP (默认)
socket.SOCK_DGRAM 数据报式socket , for UDP
socket.SOCK_RAW 原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利 用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。
socket.SOCK_RDM 是一种可靠的UDP形式,即保证交付数据报但不保证顺序。SOCK_RAM用来提供对原始协议的低级访问,在需要执行某些特殊操作时使用,如发送ICMP报文。SOCK_RAM通常仅限于高级用户或管理员运行的程序使用。
socket.SOCK_SEQPACKET 可靠的连续数据包服务
参数三:协议(这个参数用默认的就好,所以在我们创建对象的时候没有使用此参数,忘记这个参数吧)
0 (默认)与特定的地址家族相关的协议,如果是 0 ,则系统就会根据地址格式和套接类别,自动选择一个合适的协议'
UDP协议实现socket代码实例:
我们刚刚看的例子中都是使用TCP协议进行传输,下面上一段UDP的例子。
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import socket 4 ip_port = ('127.0.0.1',9999) 5 6 sk = socket.socket(socket.AF_INET,socket.SOCK_DGRAM,0) 7 while True: 8 inp = raw_input('数据:').strip() 9 if inp == 'exit': 10 break 11 sk.sendto(inp,ip_port) 12 sk.close()
#!/usr/bin/env python # -*- coding:utf-8 -*- import socket ip_port = ('127.0.0.1',9999) sk = socket.socket(socket.AF_INET,socket.SOCK_DGRAM,0) sk.bind(ip_port) while True: data = sk.recv(1024) print data
参考:
socket详解:http://www.cnblogs.com/wupeiqi/articles/5040823.html
TCP和UDP协议的区别:http://jingyan.baidu.com/article/6dad5075df3452a123e36ecb.html