Python之——网络编程笔记

1. 套接字

套接字是计算机网络数据结构,它体现了上节中所描述的“通信端点”的概念。在任何
类型的通信开始之前,网络应用程序必须创建套接字。可以将它们比作电话插孔,没有它将
无法进行通信。
有两种类型的套接字:基于文件的和面向网络的。
UNIX 套接字是我们所讲的套接字的第一个家族,并且拥有一个“家族名字”。(这块不是本文重点,不细说)
而基于网络的套接字,有自己的家族名字 AF_INET。
Python 只支持 AF_UNIX、 AF_NETLINK、 AF_TIPC 和 AF_INET 家族。在网络编程中,将会用到 AF_INET。

  • 面向连接
    实现这种连接类型的主要协议是传输控制协议(更为人熟知的是它的缩写 TCP)。为 了
    创建 TCP 套接字,必须使用 SOCK_STREAM 作为套接字类型。

  • 面向无连接
    实现这种连接类型的主要协议是用户数据报协议(更为人熟知的是其缩写 UDP)。为 了
    创建 UDP 套接字,必须使用 SOCK_DGRAM 作为套接字类型。

2. socket()模块函数

要创建套接字,必须使用 socket.socket()函数,它一般的语法如下。

socket(socket_family, socket_type, protocol=0)

为了创建 TCP/IP 套接字,可以用下面的方式调用 socket.socket()。

tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

同样,为了创建 UDP/IP 套接字,需要执行以下语句。

udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

3. 创建TCP服务器

伪代码如下:

# -*- coding: utf-8 -*
from socket import *

ss = socket() # 创建服务器套接字
ss.bind() # 套接字与地址绑定
ss.listen() # 监听连接
inf_loop: # 服务器无限循环
    cs = ss.accept() # 接受客户端连接
    comm_loop: # 通信循环
        cs.recv()/cs.send() # 对话(接收/发送)
    cs.close() # 关闭客户端套接字
ss.close() # 关闭服务器套接字#(可选)

在程序中,如果想要完成一个tcp服务器的功能,需要的流程如下:

  1. socket创建一个套接字
  2. bind绑定ip和port
  3. listen使套接字变为可以被动链接
  4. accept等待客户端的链接
  5. recv/send接收发送数据

3.1 一个很简单的tcp服务器如下:

#coding=utf-8
from socket import *

# 创建socket
tcpSerSocket = socket(AF_INET, SOCK_STREAM)

# 绑定本地信息
address = ('', 7787)
tcpSerSocket.bind(address)

# 使用socket创建的套接字默认的属性是主动的,使用listen将其变为被动的,这样就可以接收别人的链接了
tcpSerSocket.listen(5)

# 如果有新的客户端来链接服务器,那么就产生一个新的套接字专门为这个客户端服务器
# newSocket用来为这个客户端服务
# tcpSerSocket就可以省下来专门等待其他新客户端的链接
newSocket, clientAddr = tcpSerSocket.accept()

# 接收对方发送过来的数据,最大接收1024个字节
recvData = newSocket.recv(1024)
print('接收到的数据为:',recvData)

# 发送一些数据到客户端
newSocket.send("thank you !".encode())

# 关闭为这个客户端服务的套接字,只要关闭了,就意味着为不能再为这个客户端服务了,如果还需要服务,只能再次重新连接
newSocket.close()

# 关闭监听套接字,只要这个套接字关闭了,就意味着整个程序不能再接收任何新的客户端的连接
tcpSerSocket.close()

tcp的客户端要比服务器端简单很多,如果说服务器端是需要自己买手机、查手机卡、设置铃声、等待别人打电话流程的话,那么客户端就只需要找一个电话亭,拿起电话拨打即可,流程要少很多。

3.2 一个很简单的客户端如下:

#coding=utf-8
from socket import *

# 创建socket
tcpClientSocket = socket(AF_INET, SOCK_STREAM)

# 链接服务器
serAddr = ('10.88.2.192', 7787)
tcpClientSocket.connect(serAddr)

# 提示用户输入数据
sendData = input("请输入要发送的数据:")

tcpClientSocket.send(sendData.encode())

# 接收对方发送过来的数据,最大接收1024个字节
recvData = tcpClientSocket.recv(1024)
print('接收到的数据为:',recvData)

# 关闭套接字
tcpClientSocket.close()

注:以上服务端、客户端的代码已经在python3下调试通过,调试的过程中,也碰到了一些问题,记录如下:

  1. 出错NameError: name 'raw_input' is not defined
    原因出在raw_input ,python3.0版本后用input替换了raw_input 。所以是自己看的教程太老,基于python2.x,而自己用的是3.x,所以使用input就好了。
  2. 调试时出错TypeError: a bytes-like object is required, not 'str'
    这个也是版本的问题,python3.5和Python2.7在套接字返回值解码上有区别。
    参考文章:https://blog.csdn.net/yexiaohhjk/article/details/68066843
    (未完待续,待整理)

你可能感兴趣的:(Python之——网络编程笔记)