Python语言下简单socket程序报告

1 什么是Socket

在计算机通信领域,socket 被翻译为“套接字”,它是计算机之间进行通信一种约定或一种方式。通过 socket 这种约定,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据
  socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。
  我的理解就是Socket就是该模式的一个实现:即socket是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)。

2 socket服务器端代码及其解释

import socket
 
 
HOST = '127.0.0.1'
PORT = 8888
 
server = socket.socket()
server.bind((HOST, PORT))
server.listen(1)
 
print(f'the server is listening at {HOST}:{PORT}')
print('waiting for conntection...')
conn, addr
= server.accept() print(f'connect success addr={addr}') print('waiting for message') while True: msg = conn.recv(1024) print('the clint send:', msg.decode()) response = input('enter your response: ') conn.send(response.encode()) print('waiting for answer')

分析该程序:

首先,sever为一个实例化的socket套接字,随后server绑定到本地地址,以用户名:端口号的方式给出。随后对该端口进行监听。

一旦收到回复,会以元组的形式返回一个连接对象conn与地址addr。这里注意到addr地址以元组(IPaddr,port)的形式给出。随后就可以利用conn进行通信了

3 socket客户端代码及其解释

import socket
import sys

try:
    host, port = input('enter host address like host:port: ').split(':')
except ValueError:
    print('the address is wrong')
    sys.exit(-1)

if len(host) == 0 or len(port) == 0:
    print('the address is wrong')
    sys.exit(-1)
else:
    client = socket.create_connection((host, port))

    print('connect successfully. waiting for response...')

    client.send(b'hello server.')
    while True:
        response = client.recv(1024)
        print('the response is:', response.decode())
        msg = input('please enter a answer: ')
        client.send(msg.encode())
        print('waiting for response...')

首先,请用户输入地址,端口号,之后以“:”为间隔分开。如果输入出错则抛出ValueError。如果是正确的地址则创建连接。

随后在连接中进行通信。

结果大概如下图所示:

server端:

 

 

client端:

 

 可以看见能够成功运行

4 相关API及分析:

Python下我们重点分析socket接口对象。

在socket.pyi中,我们找到如下的socket类及方法定义:

class socket:
    family: int
    type: int
    proto: int

    if sys.version_info < (3,):
        def __init__(self, family: int = ..., type: int = ...,
                 proto: int = ...) -> None: ...
    else:
        def __init__(self, family: int = ..., type: int = ...,
                     proto: int = ..., fileno: Optional[int] = ...) -> None: ...

    if sys.version_info >= (3, 2):
        def __enter__(self: _SelfT) -> _SelfT: ...
        def __exit__(self, *args: Any) -> None: ...

    # --- methods ---
    # second tuple item is an address
    def accept(self) -> Tuple[socket, Any]: ...
    def bind(self, address: Union[tuple, str, bytes]) -> None: ...
    def close(self) -> None: ...
    def connect(self, address: Union[tuple, str, bytes]) -> None: ...
    def connect_ex(self, address: Union[tuple, str, bytes]) -> int: ...
    def detach(self) -> int: ...
    def fileno(self) -> int: ...

该类中详细定义了对于网络接口的使用规范。我们重点查看connect函数,其定义如下:

    def connect(self, addr):
        """Connects to remote ADDR, and then wraps the connection in
        an SSL channel."""
        self._real_connect(addr, False)

这里提供SSL加密的安全连接,我们继续查看_real_connect()内置方法:

    def _real_connect(self, addr, connect_ex):
        if self.server_side:
            raise ValueError("can't connect in server-side mode")
        # Here we assume that the socket is client-side, and not
        # connected at the time of the call.  We connect it, then wrap it.
        if self._connected:
            raise ValueError("attempt to connect already-connected SSLSocket!")
        sslobj = self.context._wrap_socket(self, False, self.server_hostname)
        self._sslobj = SSLObject(sslobj, owner=self,
                                 session=self._session)
        try:
            if connect_ex:
                rc = socket.connect_ex(self, addr)
            else:
                rc = None
                socket.connect(self, addr)
            if not rc:
                self._connected = True
                if self.do_handshake_on_connect:
                    self.do_handshake()
            return rc
        except (OSError, ValueError):
            self._sslobj = None
            raise

同函数中注释所说明的,该函数假设自己处在客户端并且没有对于目标地址的连接。该函数目的为连接到指定地址并调用相关的SSL对象对该链接进行封装。

5 Linux Socket API

因为在Python语言中,实现我上述程序的网络端口也是socket套接字,其内置方法与Linux Socket较为相似,包括bind()、 connect()等方法,差别仅仅在于实现这些函数的语言不同。

在逻辑与功能设计层面,两者思想是相似甚至相同的。

 

posted @ 2019-11-28 13:02  zyh123231  阅读(617)  评论(0)    收藏  举报