Python之BSD socket套接字编写回显客户端/服务器应用----《Python 网络编程攻略》

本例实现的功能:不管服务器从客户端收到什么输入,都会将其回显出来。

运行效果及方法如下:


  1. 如图,打开运行输入cmd,先运行服务器程序1_13a_echo_server.py,注意要输入参数--port=9900,得到界面如下:
    20170227-1.JPG
  2. 再打开一个命令窗口,运行客户端程序1_13b_echo_client.py,得到结果如下:
    20170227-2.JPG

我们看到,服务器在9900端口启动了一个监听,客户端向9900端口发送了“Test message. This will be echoed.”,而后,被服务器分了5次,全部返回了,之所以分5次是由于接受缓存大小只有8个字节。

1. 服务器程序1_13a_echo_server.py

#coding=utf_8
'''
Created on 2017-2-26

@author: lenovo
'''
import socket
import sys
import argparse

host = 'localhost'
data_payload = 2048
backlog = 5
# backlog:积压;未完成的订货;这里特指待连接队列长度。

def echo_server(port):
    #create a TCP socket
    sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    #Enable reuse address/port
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    #Bind the socket to the port
    server_address = (host,port)
    print "Starting up echo server on %s port %s" % server_address
    sock.bind(server_address)
    sock.listen(backlog)
    # 服务器端可建立连接的客户端的队列长度为 backlog=5
    # The backlog argument specifies the maximum number of 
    # queued connections and should be at least 1; 
    while True:
        print "Waiting to receive message from client"
        client,address = sock.accept()
        data = client.recv(data_payload)
        #The maximum amount of data to be received at once is specified by bufsize. 
        if data:
            print "Data : %s" %data
            client.send(data)
            print "sent %s bytes back to %s" %(data,address)
        client.close()
if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='socket server example')
    parser.add_argument('--port',action="store",dest="port",type=int,required = True)
    given_args = parser.parse_args()
    port = given_args.port
    echo_server(port)

2. 客户端程序1_13b_echo_client.py

'''
Created on 2017-2-27

@author: lenovo
'''
import socket
import sys
import argparse

host = 'localhost'

def echo_client(port):
    sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    server_address = (host,port)
    print "Connecting to %s port %s" % server_address
    sock.connect(server_address)

    try:
        message = "Test message. This will be echoed."
        print "Sending %s"  % message
        sock.sendall(message)
        amount_received = 0
        amount_expected = len(message)
        while amount_received < amount_expected:
            data = sock.recv(8)
            amount_received += len(data)
            print "Received : %s" %data
    except socket.errno, e:
        print "Socket error: %s" %str(e)
    except Exception, e:
        print "Other exception: %s" %str(e)
    finally:
        print "Closing connection to the server"
        sock.close()

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='socket server example')
    parser.add_argument('--port',action="store",dest="port",type=int,required=True)
    given_args = parser.parse_args()
    port = given_args.port
    echo_client(port) 

3. argparse用于参数的输入和解析

3.1 import argparse

Function: The argparse module makes it easy to write user friendly command line interfaces. The program defines what arguments it requires, and argparse will figure out how to parse those out of sys.argv. The argparse module also automatically generates help and usage messages and issues errors when users give the program invalid arguments.

—-使用argparse模块,可以轻松建立友好的命令行用户接口,即在用户没输入相关参数的情况下进行提示需输入参数。

3.2 argparse.ArgumentParser()

生成ArgumentParser对象

20170227-3.JPG

3.3 The add_argument() method

定义命令行参数如何被解析获取。

20170227-4.JPG

3.4 The parse_args() method

ArgumentParser.parse_args(args=None, namespace=None)

Convert argument strings to objects and assign them as attributes of the namespace. Return the populated namespace.

—-该方法用于从字符串中提取参数,提取的方法按照3.3所定义的参数解析方法。

4. socket对象的相关函数

4.1 socket.accept()

Accept a connection. The socket must be bound to an address and listening for connections.

用于接收一个连接,接受连接的socket必须绑定到一个地址和端口用于连接。

The return value is a pair (conn, address) where conn is a new socket object usable to send and receive data on the connection, and address is the address bound to the socket on the other end of the connection.

4.2 socket.bind(address)

Bind the socket to address. The socket must not already be bound. (The format of address depends on the address family — see above.)

4.3socket.close()

Close the socket. All future operations on the socket object will fail. The remote end will receive no more data (after queued data is flushed). Sockets are automatically closed when they are garbage-collected.

4.4 socket.connect(address)

Connect to a remote socket at address. (The format of address depends on the address family — see above.)

4.5 socket.listen(backlog)

Listen for connections made to the socket. The backlog argument specifies the maximum number of queued connections and should be at least 1; the maximum value is system-dependent (usually 5).

设置服务器端可建立连接的客户端的队列长度。

4.6socket.recv(bufsize[, flags])

Receive data from the socket. The return value is a string representing the data received. The maximum amount of data to be received at once is specified by bufsize. See the Unix manual page recv(2) for the meaning of the optional argument flags; it defaults to zero.

从socket连接接受数据,并定义一次获取的最大数量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值