Python中的socket

参考:http://blog.sina.com.cn/s/blog_523491650100hikg.html

         http://blog.csdn.net/ithomer/article/details/17252915


   有人说表示只学Python没有用,必须学会一个框架(比如Django和web.py)才能找到工作。其实掌握一个类似于框架的高级工具是有用的,但是基础的东西可以让你永远不被淘汰,不要被工具限制了自己的发展。今天不使用框架,也不使用Python标准库中的高级包,只使用标准库中的socket接口写一个Python服务器。

   在当今Python服务器框架 (framework, 比如Django, Twisted, web.py等等) 横行的时代,从底层的socket开始写服务器似乎是一个出力不讨好的笨方法。框架的意义在于掩盖底层的细节,提供一套对于开发人员更加友好的API,并处理诸如MVC的布局问题。框架允许我们快速的构建一个成型而且成熟的Python服务器。然而,框架本身也是依赖于底层(比如socket)。对于底层socket的了解,不仅可以帮助我们更好的使用框架,更可以让我们明白框架是如何设计的。更进一步,如果拥有良好的底层socket编程知识和其他系统编程知识,你完全可以设计并开发一款自己的框架。如果你可以从底层socket开始,实现一个完整的Python服务器,支持用户层的协议,并处理好诸如MVC(Model-View-Control)、多线程(threading)等问题,并整理出一套清晰的函数或者类,作为接口(API)呈现给用户,你就相当于设计了一个框架。

   socket接口是实际上是操作系统提供系统调用。socket的使用并不局限于Python语言,你可以用C或者JAVA来写出同样的socket服务器,而所有语言使用socket的方式都类似(Apache就是使用C实现的服务器)。而你不能跨语言的使用框架。框架的好处在于帮你处理了一些细节,从而实现快速开发,但同时受到Python本身性能的限制。我们已经看到,许多成功的网站都是利用动态语言(比如Python, Ruby或者PHP,比如twitter和facebook)快速开发,在网站成功之后,将代码转换成诸如C和JAVA这样一些效率比较高的语言,从而让服务器能更有效率的面对每天亿万次的请求。在这样一些时间,底层的重要性,就远远超过了框架。

1. TCP/IP和socket简介

   回到我们的任务。我们需要对网络传输,特别是TCP/IP协议socket有一定的了解。socket是进程间通信的一种方法,它是基于网络传输协议的上层接口。socket有许多种类型,比如基于TCP协议或者UDP协议(两种网络传输协议),其中又以TCP socket最为常用。TCP socket与双向管道(duplex PIPE)有些类似,一个进程向socket的一端写入或读取文本流,而另一个进程可以从socket的另一端读取或写入,比较特别是,这两个建立socket通信的进程可以分别属于两台不同的计算机。TCP协议,就是规定了一些通信的守则,以便在网络环境下能够有效实现上述进程间通信过程。双向管道(duplex PIPE)存活于同一台电脑中,所以不必区分两个进程的所在计算机的地址,而socket必须包含有地址信息,以便实现网络通信。一个socket包含四个地址信息: 两台计算机的IP地址和两个进程所使用的端口(port)。IP地址用于定位计算机,而port用于定位进程 (一台计算机上可以有多个进程分别使用不同的端口)。

2. TCP socket

   在互联网上,让某台计算机作为服务器。服务器开放自己的端口,被动等待其他计算机连接。当其他计算机作为客户主动使用socket连接到服务器的时候,服务器就开始为客户提供服务。在Python中,我们使用标准库中的socket包来进行底层的socket编程。

服务器端建立过程:

(1)创建socket对象。

       socket = socket. Socket(family,type)

       family:一个地址描述。目前仅支持AF_INET格式,也就是说ARPAInternet地址格式。

       type:指定socket类型。新套接口的类型描述类型,如TCP(SOCK_STREAM)和UDP(SOCK_DGRAM)。常用的socket类型有:SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等。

(2)将socket绑定到指定地址上。

        socket.bind((HOST, PORT))

       (HOST, PORT)是一个元组,分别对应主机名或IP地址+端口号(端口号对应了进程),端口号被使用则会产生error

(3)绑定后,必须准备好套接字,以便接受请求。

       socket.listen(N)

       N指定了最多连接数,至少为1,接到连接请求后,请求必须排队 ,如果多列满,则拒绝请求。

【注】这里只是指定了等待队列的容量,侦听是从accept开始。


(4)服务器套接字通过socket的accept方法等待客户请求一个连接。

       connnection, address = s.accept()

       调用accept方法,socket进入waiting(阻塞)状态。客户请求连接时,该方法建立连接并返回服务器。accept方法返回一个元组:connnection表示新的socket对象,服务器通过它与客服端通信,address表示客户的Internet地址。

(5)处理阶段

       服务器和客户端通过send和recv方法通信(传数据)。send方法返回已发送字符的个数,recv返回接受到的字符串,调用recv时需要指定一个整数控制本次调用所接受的最大数据量(如果超出量,字符串被截断),recv在接受数据时进入‘blocket’状态

(6)传输结束。调用close方法。


客户端建立过程:

(1)创建一个socket以连接服务器 socket = socket. socket(family,type);

(2)使用socket的connect方法连接服务器socket. connect((host,port));

(3)客户端和服务器通过send和recv方法通信;

(4)结束后,客户端通过close方法关闭连接。


服务器端代码:

import socket

myHost = 'localhost'
myPort = 50014
sockobj = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sockobj.bind((myHost,myPort))
sockobj.listen(5)

while True:
    print 'I am listenning'
    conn, addr = sockobj.accept()
    print "Connected By:" ,addr
    try:
        conn.settimeout(5)
        data = conn.recv(1024)
        if not data:break
        conn.send('Echo=>' + data)
    except socket.timeout:
        print 'Time Out'
    conn.close()
客户端代码:

import socket

serverHost = 'localhost'
serverPort = 50014

sockobj = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sockobj.connect((serverHost,serverPort))
sockobj.send('Hello,Server')
print sockobj.recv(1024)
sockobj.close()
运行结果:




  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值