【脚本开发-1】:网络通信开发基础[Python实现]建立 socket 连接通道,可以相互之间传输数据

TCP/IP简介

    互联网协议包含了上百种协议标准,但是最重要的两个协议是TCP和IP协议,所以,大家把互联网的协议简称TCP/IP协议。
    通信的时候,双方必须知道对方的标识,好比发邮件必须知道对方的邮件地址。互联网上每个计算机的唯一标识就是IP地址,类似10.132.3.186。如果一台计算机同时接入到两个或更多的网络,比如路由器,它就会有两个或多个IP地址,所以,IP地址对应的实际上是计算机的网络接口,通常是网卡。IP地址实际上是一个32位整数(IPv4),如192.168.119.1(把32位整数按8位分组后的数字表示)。IPv6是IPv4的升级版,是128位整数,类似于2001:0db8:85a3:0042:1000:8a2e:0370:7334
    IP协议负责把数据从一台计算机通过网络发送到另一台计算机。
    TCP协议是建立在IP协议之上,负责在两台计算机之间建立可靠连接,保证数据包按顺序到达。该协议会通过握手建立连接,然后,对每个IP包编号,确保对方按顺序收到,如果包丢掉了,就自动重发。(常用的更高级的协议是建立在TCP协议上,比如SMTP协议)
    一个TCP报文除了包含要传输的数据外,还包含源IP地址和目标IP地址,源端口和目标端口。(为什么需要端口呢?只发IP地址是不够的,一个电脑上跑着多个应用程序,比如QQ和微信,一个TCP报文发送过来后,判断发给QQ还是微信,就是用端口来分辨的。每个网络程序都向操作系统申请唯一的端口号,两个进程在两台计算机之间建立网络连接就需要各自的IP地址和各自的端口号。一个进程也可能同时与多个计算机建立链接,因此它会申请很多端口。)

TCP编程

客户端编程

    以下代码是客户端向新浪新闻服务器发送TCP请求,然后将接收到的信息输出。

  1. 首先是创建一个socket连接,使用IPv4协议和TCP协议。
  2. 然后连接新浪新闻服务器,80端口是Web服务的标准端口,其他服务都有对应的标准端口号,例如SMTP服务是25端口,FTP服务是21端口,等等。
  3. 将接收到的数据进行输出。
import socket

# 创建socket AF_INET指定使用IPv4协议(IPv6-AF_INET6) SOCK_STREAM指定使用面向流的TCP协议
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 80端口是Web服务的标准端口。
# 其他服务都有对应的标准端口号: SMTP服务是25端口,FTP服务是21端口。
s.connect(('www.sina.com.cn', 80))

# 发送数据
s.send(b'GET / HTTP/1.1\r\nHost: www.sina.com.cn\r\nConnection: close\r\n\r\n')# 接收数据
buffer = []

while  True:
    d = s.recv(1024)
    if d:
        # print(d)
        buffer.append(d)
    else:
        break
data = b''.join(buffer)
header, html = data.split(b'\r\n\r\n')

print(data)
print(header.decode('utf-8'))
print(html.decode('utf-8'))
s.close()

输出结果

服务端编程

    以下代码是服务器端代码。

  1. 首先创建一个基于IPv4和TCP协议的Socket。
  2. 绑定了本地的9999端口(小于1024的端口号必须要有管理员权限才能绑定)。
  3. 设置最大连接数为5,由于考虑到服务器可能同时响应多个客户端的请求,所以,每个连接都需要一个新的进程或者新的线程来处理。
  4. tcplink函数:首先输出接受的连接的地址,然后向客户端发送hello信息,接受从客户端传输过来的字符串,然后拼接输出。
import socket
import threading
import time

def tcplink(sock, addr):
    print("Accept new connection from %s:%s" % addr)
    sock.send(b"hello !")
    while True:
        data = sock.recv(1024)
        time.sleep(1)
        if not data:
            break
        sock.send(("nihao, %s" % data.decode('utf-8')).encode('utf-8'))
    sock.close()
    print("connection from %s:%s close" % addr)


def main():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 绑定本机地址和9999端口号
    # 小于1024的端口必须要有管理员权限才能绑定
    s.bind(('127.0.0.1', 9998))

    # 指定等待连接的最大数量为5
    s.listen(5)
    print("Waiting for connection...")

    while True:
        sock, addr = s.accept()
        t = threading.Thread(target=tcplink, args=(sock, addr))
        t.start()


if __name__ == "__main__":
    main()

客户端发送命令,服务端接收命令并执行

    为了实现客户端与以上的服务端通信,我们创建一个客户端,向服务端发送数据。连接建立后,服务器首先发一条欢迎消息,然后等待客户端数据,并加上Hello再发送给客户端。

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 9998))
# 发送数据
print(s.recv(1024).decode('utf-8'))
for data in [b'qqqq', b'wwwww', b'eeeeee']:
    s.send(data)
    print(s.recv(1024).decode('utf-8'))
s.close()

    结果如下:
在这里插入图片描述
在这里插入图片描述

UDP简介

    UDP协议与TCP协议的不同在于,它是面向无连接,不可靠的数据报协议。而且不需要建立连接就可以,只需要知道对方的IP地址和端口号,就可以直接发数据包。但是,能不能到达就不知道了。

UDP编程

    和TCP类似,使用UDP的通信双方也分为客户端和服务器。

服务端编程

  1. SOCK_DGRAM指定了这个Socket的类型是UDP。
  2. recvfrom()方法返回数据和客户端的地址与端口,服务器收到数据后,直接调用sendto()就可以把数据用UDP发给客户端。
import socket

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

s.bind(('127.0.0.1', 9998))
print("bind UDP on 9998...")

while True:
    data, addr = s.recvfrom(1024)
    print('Received from %s:%s', addr)
    s.sendto(b'Hello, %s' % data, addr)

客户端编程

  1. 不需要调用connect(),直接通过sendto()给服务器发数据。
  2. 从服务器接收数据仍然调用recv()方法。
import socket

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

for data in [b'qqq', b'www', b'eee']:
    s.sendto(data, ('127.0.0.1', 9998))
    print(s.recv(1024).decode('utf-8'))
    
s.close()

    结果如下:
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Uranusky_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值