【Python】socket编程

来源:互联网 发布:mac os 截图软件 编辑:程序博客网 时间:2024/06/11 21:15

套接字介绍

TCP/IPUDPSocket编程这些词你不会很陌生吧?随着网络技术的发展,这些词充斥着我们的耳朵。那么我想问:


1.         什么是TCP/IPUDP
2.         Socket在哪里呢?
3.         Socket是什么呢?
4.         你会使用它们吗?

什么是TCP/IPUDP

         TCP/IPTransmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,是一个工业标准的协议集,它是为广域网(WANs)设计的。
         UDPUser Data Protocol,用户数据报协议)是与TCP相对应的协议。它是属于TCP/IP协议族中的一种。
        这里有一张图,表明了这些协议的关系。

                                                                                

                                                                        图1

       TCP/IP协议族包括运输层、网络层、链路层。现在你知道TCP/IPUDP的关系了吧。
Socket在哪里呢?
       
在图1中,我们没有看到Socket的影子,那么它到底在哪里呢?还是用图来说话,一目了然。



2

       原来Socket在这里。
Socket是什么呢?
       Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
你会使用它们吗?
       
前人已经给我们做了好多的事了,网络间的通信也就简单了许多,但毕竟还是有挺多工作要做的。以前听到Socket编程,觉得它是比较高深的编程知识,但是只要弄清Socket编程的工作原理,神秘的面纱也就揭开了。
       一个生活中的场景。你要打电话给一个朋友,先拨号,朋友听到电话铃声后提起电话,这时你和你的朋友就建立起了连接,就可以讲话了。等交流结束,挂断电话结束此次交谈。    生活中的场景就解释了这工作原理,也许TCP/IP协议族就是诞生于生活中,这也不一定。

      

3

       先从服务器端说起。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。

Python的套接字模块

Python 提供了两个基本的 socket 模块。

   第一个是 Socket,它提供了标准的 BSD Sockets API。

   第二个是 SocketServer, 它提供了服务器中心类,可以简化网络服务器的开发。

下面讲的是Socket模块功能

1、Socket 类型

套接字格式:

socket(family,type[,protocal]) 使用给定的地址族、套接字类型、协议编号(默认为0)来创建套接字。

socket类型

描述

socket.AF_UNIX

只能够用于单一的Unix系统进程间通信

socket.AF_INET

服务器之间网络通信

socket.AF_INET6

IPv6

socket.SOCK_STREAM

流式socket , for TCP

socket.SOCK_DGRAM

数据报式socket , for UDP

socket.SOCK_RAW

原始套接字,普通的套接字无法处理ICMPIGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。

socket.SOCK_SEQPACKET

可靠的连续数据包服务

创建TCP Socket

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

创建UDP Socket

s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)


2、Socket 函数

注意点:

1TCP发送数据时,已建立好TCP连接,所以不需要指定地址。UDP是面向无连接的,每次发送要指定是发给谁。

2)服务端与客户端不能直接发送列表,元组,字典。需要字符串化repr(data)

socket函数

描述

服务端socket函数

s.bind(address)

将套接字绑定到地址AF_INET,以元组(host,port)的形式表示地址.

s.listen(backlog)

开始监听TCP传入连接。backlog指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5就可以了。

s.accept()

接受TCP连接并返回(conn,address,其中conn是新的套接字对象,可以用来接收和发送数据。address是连接客户端的地址。

客户端socket函数

s.connect(address)

连接到address处的套接字。一般address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。

s.connect_ex(adddress)

功能与connect(address)相同,但是成功返回0,失败返回errno的值。

公共socket函数

s.recv(bufsize[,flag])

接受TCP套接字的数据。数据以字符串形式返回,bufsize指定要接收的最大数据量。flag提供有关消息的其他信息,通常可以忽略。

s.send(string[,flag])

发送TCP数据。将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。

s.sendall(string[,flag])

完整发送TCP数据。将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。

s.recvfrom(bufsize[.flag])

接受UDP套接字的数据。与recv()类似,但返回值是(data,address)。其中data是包含接收数据的字符串,address是发送数据的套接字地址。

s.sendto(string[,flag],address)

发送UDP数据。将数据发送到套接字,address是形式为(ipaddrport)的元组,指定远程地址。返回值是发送的字节数。

s.close()

关闭套接字。

s.getpeername()

返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)。

s.getsockname()

返回套接字自己的地址。通常是一个元组(ipaddr,port)

s.setsockopt(level,optname,value)

设置给定套接字选项的值。

s.getsockopt(level,optname[.buflen])

返回套接字选项的值。

s.settimeout(timeout)

设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。一般,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作(如connect()

s.gettimeout()

返回当前超时期的值,单位是秒,如果没有设置超时期,则返回None

s.fileno()

返回套接字的文件描述符。

s.setblocking(flag)

如果flag0,则将套接字设为非阻塞模式,否则将套接字设为阻塞模式(默认值)。非阻塞模式下,如果调用recv()没有发现任何数据,或send()调用无法立即发送数据,那么将引起socket.error异常。

s.makefile()

创建一个与该套接字相关连的文件



Python的套接字实现

我们的套接字编程分为服务器和客户端两部分。

服务器端;

1. 建立socket, s = socket.socket()

2.绑定端口, s.bind( (host, port) )

3.监听端口, s.listen()

4.进入循环,不断接受客户端请求, s.accept()

5.建立连接,接收传来的数据,发送数据  s.recv(), s.sendall()

'''服务器端先初始化socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞等待客户端连接。这事如果有客户端初始化一个socket,且尝试连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端端发送数据请求,服务器端接收并处理请求,然后把回应数据发给客户端,客户端读取数据,最后关闭连接,交互结束'''import socketimport subprocess  #执行系统命令模块HOST = '127.0.0.1'PORT = 50007s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)#服务器之间网络通信,流式socket(TCP)s.bind((HOST, PORT))s.listen(1)while 1:    conn, addr = s.accept()  #接受TCP连接,并返回新的套接字与ip地址    print("connected by", addr)    while 1:        data = conn.recv(1024)        #接受套接字的数据,数据以字符串刑事返回,1024指要接受的最大数据量        proc_status,proc_result = subprocess.getstatusoutput(data)        #返回两个结果,第一个是状态,成功则为0,第二个是执行成功或失败的输出信息        if len(proc_result.strip()) == 0:        <span style="white-space:pre"></span>#如果输出结果长度为0,则告诉客户端完成。        #此用法针对于创建文件或目录,创建成功不会有输出信息            conn.sendall('Done')            #完整发送TCP数据,将string中的数据发送到连接的套接字            #但在返回之前会尝试发送所有数据,成功则返回None,失败则抛出异常        else:            conn.sendall(proc_resut)conn.close()
>>> help(subprocess.getstatusoutput)
Help on function getstatusoutput in module subprocess:


getstatusoutput(cmd)
    Return (status, output) of executing cmd in a shell.
    
    Execute the string 'cmd' in a shell with os.popen() and return a 2-tuple
    (status, output).  cmd is actually run as '{ cmd ; } 2>&1', so that the
    returned output will contain output or error messages.  A trailing newline
    is stripped from the output.  The exit status for the command can be
    interpreted according to the rules for the C function wait().  Example:
    
    >>> import subprocess
    >>> subprocess.getstatusoutput('ls /bin/ls')
    (0, '/bin/ls')
    >>> subprocess.getstatusoutput('cat /bin/junk')
    (256, 'cat: /bin/junk: No such file or directory')
    >>> subprocess.getstatusoutput('/bin/junk')
    (256, 'sh: /bin/junk: not found')
subprocess.getstatusoutput(command)
使用os. getstatusoutput ()函数执行command命令并返回一个元组(status,output),
分别表示command命令执行的返回状态和执行结果。对command的执行实际上是按照{command;}
2>&1的方式,所以output中包含控制台输出信息或者错误信息。output中不包含尾部的换行符。

客户端:

1. 建立socket并绑定端口, s = socket.socket(), s.bind()

2. 连接后发送和接收数据  s.sendall(), s.recv()

3.传输完毕,关闭套接字  s.close()

import socketHOST = '127.0.0.1'PORT = 50007s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)s.connect((HOST, PORT))while 1:    cmd = input("Please input command: ")    s.sendall(cmd)    data = s.recv()    print(data)s.close()


0 0
原创粉丝点击