网络编程

简介

网络编程就是实现计算机与计算机、计算机与服务器之间的连接。例如你在访问某个网站的时候,你的计算机就与该网站的服务器连接起来了,同时,该服务器也将网页以数据的形式传回给计算机。

socket &socketserver

关于socket模块,官方文档(socket)是这么描述的:

This module provides access to the BSD socket interface. It is available on all modern Unix systems, Windows, MacOS, and probably additional platforms.
Note Some behavior may be platform dependent, since calls are made to the operating system socket APIs.
The Python interface is a straightforward transliteration of the Unix system call and library interface for sockets to Python’s object-oriented style: the socket() function returns a socket object whose methods implement the various socket system calls. Parameter types are somewhat higher-level than in the C interface: as with read() and write() operations on Python files, buffer allocation on receive operations is automatic, and buffer length is implicit on send operations.

看不懂对吧,我也看不懂。大概意思就是低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口的全部方法。其中的函数和方法等都可以在官方文档上找到。

关于socketserver,官方文档socketserver 是这么描述的:

The socketserver module simplifies the task of writing network servers.

然后就是一系列的类和函数的介绍了。总的来说,这个模块就是简化了网络服务器的开发。

TCP编程

TCP服务器端编程一般分为5个步骤:
1)创建socket,绑定socket到本地IP与端口;
2)开始监听连接;
3)进入循环并不断接收客户端请求;
4)接收数据并发送相应的数据给客户端;
5)传输完毕,关闭socket。
客户端编程步骤如下:
1)创建socket,连接服务器;
2)连接后发送数据和接收数据;
3)传输完毕,关闭socket。
下面用一个例子来说明(以下代码学习自《Python爬虫开发与项目实战》):
首先对客户端进行编程:

####TCP_client####
import socket

#初始化socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#连接目标IP与端口
s.connect(('127.0.0.1',9999))
#接受消息
print("--->>",s.recv(1024).decode("utf-8"))
#发送消息
s.send("hello, from client")
print("--->>",s.recv(1024).decode("utf-8"))
s.send(b'exit')
#关闭socket
s.close()

如果直接运行这个程序,会出现这样的结果:
这里写图片描述
对上面的一些函数进行简单解释:socket.AF_INET 服务器间的通信(一种socket的类型);socket.SOCK_STREAM 流式socket,用于TCP;socket.connect()在地址处连接到远程套接字。(地址的格式取决于地址族);socket.recv() 从socket中获得数据;decode() 解码,socket.send() 发送数据给socket,其中b 代表byte;socket.close() 关闭socket。

然后是对服务器端编程(服务器端编程比较复杂):

####TCP_server####
import socket
import threading
import time

def DealClient(sock,addr):
    ##接受传来数据并发送数据
    print("accept new connection from %s:%s... " % addr)
    sock.send(b"hello, I am server!")
    while True:
        data = sock.recv(1024)
        time.sleep(1)
        if not data or data.decode("utf-8") == "exit":
            break
        print( "--->>%s" % data.decode("utf-8"))
        sock.send((b"Loop message : %s!" % data.decode("utf-8").encode("utf-8")))
    ##关闭socket
    sock.close()
    print("connection from %s:%s closed " % addr)

if __name__ == "__main__":
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(("127.0.0.1",9999))
    ##建立监听
    s.listen(5)
    print("waiting for connection...")
    while True:
        ##接收一个新连接
        sock,addr = s.accept()
        ##创建新线程来处理TCP连接
        t = threading.Thread(target = DealClient, args=(sock,addr))
        t.start()

这里对书上的一些代码进行了修改。然后对其中的一些语句进行解释:socket.bind() 将socket绑定到地址;socket.listen() 监听,保证服务器能够得到连接;socket.accept() 接受连接。
在运行的时候,先启动服务器端(直接点击运行按钮),然后打开cmd,到客户端所在的目录下,输入python 文件名.py 启动客户端即可。运行结果图如下:
服务器端:
这里写图片描述
客户端:
这里写图片描述
关于端口选择为9999 是因为端口号小于1024的是Internet标准服务的端口,端口号大于1024的,可以任意使用。而地址127.0.0.1 是一个特殊的IP地址,表示本机地址,如果绑定到这个地址,客户端必须同时在本机运行才能连接,也就是说,外部的计算机无法连接进来。

UDP编程

TCP是面向连接的,是需要双方建立一个可信的连接通道然后进行数据传输,而UDP是无连接的,使用UDP协议时,是不需要建立连接,只需要知道对方的IP和端口号,不关心传输的可靠性和准确性。但是UDP的速度要比TCP快得多。
UDP编程服务器端运行步骤如下:
1)创建socket,绑定指定的地址和端口;
2)直接发送和接受数据;
3)关闭socket。
客户端创建了socket之后就可以直接与服务器端通信和数据交流了。例子如下:
客户端:

####UDP_client####
import socket

#初始化socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

for data in [b"hello!",b"world",b"I am Nancy"]:
    #发送数据
    s.sendto(data, ("127.0.0.1",9999))
    #接受消息
    print("--->>",s.recv(1024).decode("utf-8"))
#关闭socket
s.close()

直接运行代码会得到下面的结果:
这里写图片描述
前面也说了,UDP没有进行连接便发送数据,所以在没有启动服务器端的时候,会将这种强制性的发送数据拦截关闭。
服务器端的编程如下:

####UDP_server####
import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('127.0.0.1',9999))
print("Bind the address successfully!")
while True:
    data, addr = s.recvfrom(1024)
    print("received from %s:%s ." % addr)
    s.sendto(b"hello! Nancy! I am server! %s" % data,addr)

对上述代码中一些关键部分做解释:socket.SOCK_DGRAM 数据报式的socket,用于UDP;socket.sendto() 将数据发送给socket,此时socket不应该连接到远程的socket,因为目的socket是由地址指定的;socket.recvfrom() 从socket中获得数据,返回值是一对(字节,地址),其中字节是表示接收到的数据的字节对象,地址是socket发送数据的地址。
和TCP一样,先启动服务器端,再启动客户端,运行结果如下:
服务器端:
这里写图片描述
客户端:
这里写图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值