Python进阶【第一篇】socket,python进阶socket

澳门新葡亰网址 1

本文由码农网 –
王国峰原创翻译,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划!

Python进阶【第一篇】socket,python进阶socket

想要构建聊天应用,或者甚至是游戏吗?那么,socket服务器将成为你迈出的第一步。一旦你了解了创建服务器的基本功能,那么后续的优化步骤就会变得同样简单。

1.socket模块

要使用socket.socket()函数来创建套接字。其语法如下:

socket.socket(socket_family,socket_type,protocol=0)

 

socket_family可以是如下参数:

  socket.AF_INET IPv4(默认)
  socket.AF_INET6 IPv6

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

socket_type可以是如下参数:

  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 可靠的连续数据包服务

protocol参数:

  0  (默认)与特定的地址家族相关的协议,如果是 0
,则系统就会根据地址格式和套接类别,自动选择一个合适的协议

socket服务器的工作方式是这样的,不间断地运行以等待客户端的连接。一旦客户端连接上了,服务器就会将它添加到客户名单中,然后开始等待来自客户端的消息。

2.套接字对象内建方法

服务器端套接字函数

s.bind()   绑定地址(ip地址,端口)到套接字,参数必须是元组的格式例如:s.bind((‘127.0.0.1’,8009))

s.listen(5)  开始监听,5为最大挂起的连接数

s.accept()  被动接受客户端连接,阻塞,等待连接

客户端套接字函数

s.connect()  连接服务器端,参数必须是元组格式例如:s.connect((‘127,0.0.1’,8009))

公共用途的套接字函数

s.recv(1024)  接收TCP数据,1024为一次数据接收的大小

s.send(bytes)  发送TCP数据,python3发送数据的格式必须为bytes格式

s.sendall()  完整发送数据,内部循环调用send

s.close()  关闭套接字

澳门新葡亰网址 1

实例1.简单实现socket程序

server端

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
import socket
import time
IP_PORT = ('127.0.0.1',8009)
BUF_SIZE = 1024

tcp_server = socket.socket()
tcp_server.bind(IP_PORT)
tcp_server.listen(5)

while True:
    print("waiting for connection...")
    conn,addr = tcp_server.accept()
    print("...connected from:",addr)
    while True:
        data = tcp_server.recv(BUF_SIZE)
        if not data:break
        tcp_server.send('[%s] %s'%(time.ctime(),data))

tcp_server.close()

以上代码解释:

1~4行

第一行是Unix的启动信息行,随后导入time模块和socket模块

5~10行

IP_PORT为全局变量声明了IP地址和端口,表示bind()函数绑定在此地址上,把缓冲区的大小设定为1K,listen()函数表示最多允许多少个连接同时进来,后来的就会被拒绝掉

11~到最后一行

在进入服务器的循环后,被动等待连接的到来。当有连接时,进入对话循环,等待客户端发送数据。如果消息为空,表示客户端已经退出,就跳出循环等待下一个连接到来。得到客户端消息后,在消息前面加一个时间戳然后返回。最后一行不会执行,因为循环不会退出所以服务端也不会执行close()。只是提醒不要忘记调用close()函数。

client端  

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
import socket

HOST = '127.0.0.1'
PORT = 8009
BUF_SIZE = 1024
ADDR = (HOST,PORT)

client = socket.socket()
client.connect(ADDR)

while True:
    data = input(">>> ")
    if not data:break
    client.send(bytes(data,encoding='utf-8'))
    recv_data = client.recv(BUF_SIZE)
    if not recv_data:break
    print(recv_data.decode())

client.close()

5~11行

HOST和PORT变量表示服务器的IP地址与端口号。由于演示是在同一台服务器所以IP地址都是127.0.0.1,如果运行在其他服务器上要做相应的修改。端口号要与服务器端完全相同否则无法通信。缓冲区大小还是1K。

客户端套接字在10行创建然后就去连接服务器端

13~21行

客户端也无限循环,客户端的循环在以下两个条件的任意一个发生后就退出:1.用户输入为空的情况或者服务器端响应的消息为空。否则客户端会把用户输入的字符串发送给服务器进行处理,然后接收显示服务器返回来的带有时间戳的字符串。

运行客户端程序与服务端程序

以下是客户端的输入与输出

[[email protected] 博客示例]# python3 tclient.py 
>>> hello
[Thu Sep 15 22:29:12 2016] b'hello'
>>> nihao
[Thu Sep 15 22:29:32 2016] b'nihao'

以下是服务端输出

[[email protected] 博客示例]# python3 tserver.py 
waiting for connection...
...connected from: ('127.0.0.1', 55378)

不要走开,下面是完整的源代码:

 3.socketserver模块

socketserver是标准库中的一个高级别的模块。用于简化实现网络客户端与服务器所需要的大量样板代码。模块中已经实现了一些可以使用的类。

实例1:使用socketserver实现与上面socket()实例一样的功能

服务端程序代码

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
import socketserver
import time

HOST = '127.0.0.1'
PORT = 8009
ADDR = (HOST,PORT)
BUF_SIZE = 1024

class Myserver(socketserver.BaseRequestHandler):
    def handle(self):
        while True:
            print("...connected from:",self.client_address)
            data = self.request.recv(BUF_SIZE)
            if not data:break
            self.request.send(bytes("%s %s"%(time.ctime(),data)))

server = socketserver.ThreadingTCPServer(ADDR,Myserver)
print("waiting for connection...")
server.serve_forever()

11~17行

主要的工作在这里。从socketserver的BaseRequestHandler类中派生出一个子类,并重写handle()函数。

在有客户端发进来的消息的时候,handle()函数就会被调用。

19~21行

代码的最后一部分用给定的IP地址和端口加上自定义处理请求的类(Myserver)。然后进入等待客户端请求与处理客户端请求的无限循环中。

客户端程序代码

import socket
HOST = '127.0.0.1'
PORT = 8009
ADDR = (HOST,PORT)
BUF_SIZE = 1024

client = socket.socket()
client.connect(ADDR)

while True:
    data = input(">>> ")
    if not data:continue
    client.send(bytes(data,encoding='utf-8'))
    recv_data = client.recv(BUF_SIZE)
    if not recv_data:break
    print(recv_data.decode())

client.close()

执行服务端和客户端代码  

下面是客户端输出

[[email protected] blog示例2]# python3 tsocketclient.py 
>>> hello
Thu Sep 15 23:53:31 2016 b'hello'
>>> nihao
Thu Sep 15 23:53:49 2016 b'nihao'
>>> hehe
Thu Sep 15 23:53:53 2016 b'hehe'

澳门新葡亰网址,下面是服务端输出

[[email protected] blog示例2]# python3 tsocketserver.py 
waiting for connection...
...connected from: ('127.0.0.1', 55385)
...connected from: ('127.0.0.1', 55385)
...connected from: ('127.0.0.1', 55385)
...connected from: ('127.0.0.1', 55385)

 

1.socket模块 要使用socket.socket()函数来创建套接字。其语法如下:
socket.socket(socket_family,socket_type,…

// Set time limit to indefinite execution
set_time_limit (0);

// Set the ip and port we will listen on
$address = 'localhost';
$port = 10000;
$max_clients = 10;

// Array that will hold client information
$client = Array();

// Create a TCP Stream socket
$sock = socket_create(AF_INET, SOCK_STREAM, 0);
// Bind the socket to an address/port
socket_bind($sock, $address, $port) or die('Could not bind to address');
// Start listening for connections
socket_listen($sock);

echo "Waiting for connections...rn";

// Loop continuously
while (true) {
    // Setup clients listen socket for reading
    $read[0] = $sock;
    for ($i = 0; $i < $max_clients; $i++) {
        if (isset($client[$i]['sock']))
            $read[$i + 1] = $client[$i]['sock'];
    }
    // Set up a blocking call to socket_select()
    if (socket_select($read, $write = NULL, $except = NULL, $tv_sec = 5) < 1)
        continue;
    /* if a new connection is being made add it to the client array */
    if (in_array($sock, $read)) {
        for ($i = 0; $i < $max_clients; $i++) {
            if (empty($client[$i]['sock'])) {
                $client[$i]['sock'] = socket_accept($sock);
                echo "New client connected $irn";
                break;
            }
            elseif ($i == $max_clients - 1)
                echo "Too many clients...rn";
        }
    } // end if in_array

    // If a client is trying to write - handle it now
    for ($i = 0; $i < $max_clients; $i++) { // for each client
        if (isset($client[$i]['sock'])) {
            if (in_array($client[$i]['sock'], $read)) {
                $input = socket_read($client[$i]['sock'], 1024);
                if ($input == null) {
                    echo "Client disconnecting $irn";
                    // Zero length string meaning disconnected
                    unset($client[$i]);
                } else {
                    echo "New input received $irn";
                    // send it to the other clients
                    for ($j = 0; $j < $max_clients; $j++) {
                        if (isset($client[$j]['sock']) && $j != $i) {
                            echo "Writing '$input' to client $jrn";
                            socket_write($client[$j]['sock'], $input, strlen($input));
                        }
                    }
                    if ($input == 'exit') {
                        // requested disconnect
                        socket_close($client[$i]['sock']);
                    }
                }
            } else {
                echo "Client disconnected $irn";
                // Close the socket
                socket_close($client[$i]['sock']);
                unset($client[$i]);
            }
        }
    }
} // end while
// Close the master sockets
socket_close($sock);

啊呀,乍一看这似乎是一个大工程,但是我们可以先将它分解为几个较小的部分。第一部分是创建服务器。Lines:2至20。

这部分代码设置了变量、地址、端口、最大客户端和客户端数组。接下来创建socket并将其绑定到我们指定的地址和端口上。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

相关文章

网站地图xml地图