python学习之 socket

Socket的中文名

套接字(socket):源IP地址和目的IP地址以及源端口号和目的端口号的组合称为套接字。其用于标识客户端请求的服务器和服务

它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。

socket的作用:

区分不同应用程序进程间的网络通信和连接,主要有3个参数:通信的IP地址、使用的传输层协议(TCP或UDP)和使用的端口号。Socket原意是 “插座”。通过将这3个参数结合起来,与一个“插座”Socket绑定,应用层就可以和传输层通过套接字接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。(需要源IP,源端口,目的IP,目的端口,协议才能准确区分不同的应用程序(端口号也称作应用程序编号))

Socket可以看成在两个程序进行通讯连接中的一个端点,是连接应用程序和网络 驱动程序的桥梁,Socket在应用程序中创建,通过绑定与网络驱动建立关系。此后,应用程序送给Socket的数据,由Socket交给网络驱动程序向网络上发送出去。计算机从网络上收到与该Socket绑定IP地址和 端口号相关的数据后,由网络驱动程序交给Socket,应用程序便可从该Socket中提取接收到的数据,网络应用程序就是这样通过Socket进行数据的发送与接收的。

官方文档:

socket编程howto:http://python.usyiyi.cn/documents/python_278/howto/sockets.html#socket-howto

Sockets

I’m only going to talk about INET sockets, but they account for at least 99% of the sockets in use.And I’ll only talk about STREAM sockets - unless you really know what you’re doing (in which case this HOWTO isn’t for you! ), you’ll get better behavior and performance from a STREAM socket than anything else. I will try to clear up the mystery of what a socket is, as well as some hints on how to work with blocking and non-blocking sockets. But I’ll start by talking about blocking sockets.You’ll need to know how they work before dealing with non-blocking sockets.(本文只涉及Inet socket,但是它已经包含了99%的socket使用)

(关于socket 的 block 和 non-block:By default, socket operations are blocking: when the thread calls a method like connect orrecv, it pauses until the operation completes.2 block的意义是socket在调用一个方法后会一直等待这个socket操作完成才会进行下一步操作)

Part of the trouble with understanding these things is that “socket” can mean a number of subtly different things, depending on context. So first, let’s make a distinction between a “client” socket - an endpoint of a conversation, and a “server” socket, which is more like a switchboard operator(接线员). The client application (your browser, for example) uses “client” sockets exclusively; the web server it’s talking to uses both “server” sockets and “client” sockets.(浏览器只使用client socket,而服务器同时使用client socket和server scoket)


Creating a Socket

Roughly speaking, when you clicked on the link that brought you to this page, your browser did something like the following:(当你在访问这个链接的时候,浏览器做了以下的事情)

#create an INET, STREAMing socket
s = socket.socket(
    socket.AF_INET, socket.SOCK_STREAM)
#now connect to the web server on port 80
# - the normal http port
s.connect(("www.mcmillan-inc.com", 80))

When the connect completes, the socket s can be used to send in a request for the text of the page.The same socket will read the reply,and then be destroyedThat’s right, destroyed. Client sockets are normally only used for one exchange (or a small set of sequential exchanges).(当这个连接完成的时候,这个叫做s的socket就可以用来发送获取页面文本的请求,这个socket也会读取回复。在这之后,这个socke就会被销毁。注意,每个socket一般在进行一次信息交换后就会被销毁)

What happens in the web server is a bit more complex. First, the web server creates a “server socket”:(server socket的创建更加麻烦一些)

#create an INET, STREAMing socket
serversocket = socket.socket(
    socket.AF_INET, socket.SOCK_STREAM)
#bind the socket to a public host,
# and a well-known port
serversocket.bind((socket.gethostname(), 80))
#become a server socket
serversocket.listen(5)

A couple things to notice: we used socket.gethostname()  so that the socket would be visible to the outside worldIf we had used s.bind(('localhost', 80)) or s.bind(('127.0.0.1', 80)) we would still have a “server” socket, but one that was only visible within the same machine. s.bind(('', 80))specifies that the socket is reachable by any address the machine happens to have(我们应该用socket.gethostname()来创建server socket,这样能使得服务器在网络上是可见的)

A second thing to note: low number ports are usually reserved for “well known” services (HTTP, SNMP etc). If you’re playing around, use a nice high number (4 digits).(很多小于3位数的端口已经被保留作为一些特定用途,个人用途最好使用4digts以上的端口)

Finally, the argument to listen tells the socket library that we want it to queue up as many as 5 connect requests (the normal max) before refusing outside connections. If the rest of the code is written properly, that should be plenty.(listen方法告诉server socket它能够同时处理5个connet请求,剩余的请求会被服务器拒绝)

Now that we have a “server” socket, listening on port 80, we can enter the mainloop of the web server:

while 1:
    #accept connections from outside
    (clientsocket, address) = serversocket.accept()
    #now do something with the clientsocket
    #in this case, we'll pretend this is a threaded server
    ct = client_thread(clientsocket)
    ct.run()

There’s actually 3 general ways in which this loop could work - dispatching a thread to handleclientsocket, create a new process to handle clientsocket, or restructure this app to use non-blocking sockets,(server socket一般有3种方式处理请求:分配一个线程处理clientsocket,创建一个进程处理clentsocket,或者让这个软件使用non-blocking sockets)


  The important thing to understand now is this: this is all a “server” socket does.  It doesn’t send any data.  It doesn’t receive any data.  It just produces “client” sockets.  Each clientsocket is created in response to some other “client” socket doing a connect()to the host and port we’re bound to.  As soon as we’ve created that clientsocket, we go back to listening for more connections.  The two “clients” are free to chat it up - they are using some dynamically allocated port which will be recycled when the conversation ends.(对于server socket,它只是做监听这件事,并不接受任何数据,也不发送任何数据。服务器socket只会在其他client socket发出connect请求的时候创建一个clent socket。我们可以通过这个clientsocket自由交换数据)

IPC (Inter-Process Communication,进程间通信)

If you need fast IPC between two processes on one machine, you should look into whatever form of shared memory the platform offers. A simple protocol based around shared memory and locks or semaphores is by far the fastest technique.

If you do decide to use sockets, bind the “server” socket to 'localhost'On most platforms, this will take a shortcut around a couple of layers of network code and be quite a bit faster.(在一台机器上进行进程间通信的时候,你可以使用socket的localhost )

Using a Socket

The first thing to note, is that the web browser’s “client” socket and the web server’s “client” socket are identical beasts. That is, this is a “peer to peer” conversation.(首先要注意的是,你的浏览器使用的client socket和服务器的clent socket是同样的东西,这是一种对等网络


Now there are two sets of verbs to use for communication. 
You can use send and recv, or you can transform your client socket into a file-like beast and use read and write. (现在我们有两种使用socket 通信的方式 send 和 recv,或者你也可以把socket 转换为一种类似文件IO的对象,并使用熟悉的文件IO操作read和write)

 The latter is the way Java presents its sockets. I’m not going to talk about it here, except to warn you that you need to useflush on sockets. These are buffered “files”, and a common mistake is to write something, and then read for a reply. Without a flush in there, you may wait forever for the reply, because the request may still be in your output buffer.

(后一种文件IO的方式是JAVA对待socket的方式。如果你要使用这种方式,我需要提醒你需要对socket使用flush操作,因为这种操作是使用缓冲区的。常见的错误是你向socket write了一些内容,然后使用read等待回复,在使用flush之前,你可能永远无法收到回复,因为你wrte的内容还停留在缓冲区里。)

Now we come to the major stumbling block of sockets - send and recv operate on the network buffers. They do not necessarily handle all the bytes you hand them (or expect from them), because their major focus is handling the network buffers. In general, they return when the associated network buffers have been filled (send) or emptied (recv)They then tell you how many bytes they handled. It is your responsibility to call them again until your message has been completely dealt with.(现在,让我们看看socket最让人头疼的部分,send和recv操作。send和recv操作)

When a recv returns 0 bytes, it means the other side has closed (or is in the process of closing) the connection. You will not receive any more data on this connection. Ever. You may be able to send data successfully; I’ll talk more about this later.(当socket的recv方法返回0字节的时候,这个socket已经被销毁了,虽然你仍然可以发送数据)

A protocol like HTTP uses a socket for only one transfer. The client sends a request, then reads a reply. That’s it. The socket is discarded. This means that a client can detect the end of the reply by receiving 0 bytes.(很多协议比如http协议都只用socket做一次数据交换,交换完成之后,这个socket就被销毁了)

But if you plan to reuse your socket for further transfers, you need to realize that there is no EOT on a socket. I repeat: if a socket send or recv returns after handling 0 bytes, the connection has been broken. If the connection has not been broken, you may wait on a recv forever, because the socket will not tell you that there’s nothing more to read (for now). Now if you think about that a bit, you’ll come to realize a fundamental truth of sockets: messages must either be fixed length (yuck),or be delimited (shrug), or indicate how long they are (much better), or end by shutting down the connectionThe choice is entirely yours, (but some ways are righter than others).(但如果你想要再次使用这个socket继续传输,你需要明白当socket 的 send 和recv都返回0的时候,这个socket已经失效了。否则的话,recv要么会返回完整长度的数据,要么会返回部分长度的数据,要么返回数据的长度)

一个send模型

class mysocket:
    '''demonstration class only
      - coded for clarity, not efficiency
    '''

    def __init__(self, sock=None):
        if sock is None:
            self.sock = socket.socket(
                socket.AF_INET, socket.SOCK_STREAM)
        else:
            self.sock = sock

    def connect(self, host, port):
        self.sock.connect((host, port))

    def mysend(self, msg):
        totalsent = 0
        while totalsent < MSGLEN:
            sent = self.sock.send(msg[totalsent:])
            if sent == 0:
                raise RuntimeError("socket connection broken")
            totalsent = totalsent + sent

    def myreceive(self):
        chunks = []
        bytes_recd = 0
        while bytes_recd < MSGLEN:
            chunk = self.sock.recv(min(MSGLEN - bytes_recd, 2048))
            if chunk == '':
                raise RuntimeError("socket connection broken")
            chunks.append(chunk)
            bytes_recd = bytes_recd + len(chunk)
        return ''.join(chunks)
大牛博客:http://yangrong.blog.51cto.com/6945369/1339593/

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

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

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

下面讲的是Socket模块功能

1、Socket 类型

套接字格式:

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

socket类型

描述

socket.AF_UNIX

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

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值