python——socket编程

客户端/服务器架构
服务器就是一系列的硬件或软件,为一个或多个客户端提供所需的服务,它存在的唯一目的就是等待客户端的请求,并响应它们,然后等待更多的请求。
客户端/服务器网络编程
在服务器响应客户端请求之前,必须进行一些初步的设置流程来为之后的工作做准备。首先会创建一个通信端点,它能够使服务器监听请求。可以把服务器当作公司的前台,或者应答公司主线呼叫的总计接线员。一旦电话号码和设备安装成功且接线员到达时,服务就可以开始了。
客户端所做的就比较简单了,只是创建它的单一通信点,然后建立一个服务器的连接,然后客户端就可以发出请求,该请求包含任何必要的数据交换。一旦请求被服务器处理,且客户端收到结果或某种确认信息此次通信就会结束
套接字:通信端点
套接字是计算机网络数据结构,它体现了通信端点的概念,在任何类型的通信开始之前,网络应用程序必须创建套接字。可以比作电话插孔,内有它就无法进行通信。套接字类型分为:基于文件(进程间通信)和面象网络。
套接字地址:主机-端口对
如果一个套接字像一个电话插孔——允许通信的一些基础设施,那么主机名和端口号就像区号和电话号码的组合。除非知道端口号和地址,此外,事先说明
必须有其他人在另一端接听。有效端口号范围0~65535。如果在使用POSIX兼容的系统,那么可以在/etc/services文件中找到预留端口号的列表。

面向连接的套接字和无连接的套接字

不管采用哪种地址家族,都有两种不同风格的套接字连接。


面向连接的套接字
面向连接的套接字,这意味着进行通信之前必须先建立连接。也称为虚拟电路或流套接字。
实现这种连接类型的主要协议是传输控制协议(TCP),为了创建TCP套接字,必须使用SOCK_STREAM作为套接字类型,TCP套接字的名字SOCK_STREAM基于流套接字的其中一种表示。因为这些套接字的网络版本使用因特网协议(IP)来搜索网络中的主机,所以整个系统通常结合这两种协议(TCP和IP)来进行。
TCP的优点:可靠稳定,体现在TCP在传递数据之前会有三次握手来建立连接,而在数据传递时有确认、窗口、重传和拥塞控制机制,在数据传输完之后还会断开连接来节约系统资源。
TCP缺点:慢,效率低,占用系统资源高,易被攻击。TCP在传输数据之前要先建立连接,这会消耗时间,而且在数据传递时,确认机制、重传机制、拥塞机制会消耗大量的时间。因为TCP有确认机制、三次握手机制,这些导致TCP容易被人利用。
TCP三次握手过程
1.主机A通过向主机B发送一个含有同步序列号的标值位的数据段,向主机B请求建立连接,通过这个数据段主机A告诉主机B两件事情:我想要和你通信;你可以用哪个序列号作为起始数据段来回应我。
2.主机B收到主机A的请求之后,用一个带有确认应答(ACK)和同步序列号(SYN)标志位的数据段响应主机A,也告诉主机A两件事情:我已经收到你的请求了,你可以传输数据了;你要用哪个序列号作为起始数据段来回应我。
3.主机A收到这个数据段后,再发送一个确认应答,确认已收到主机B的数据段:“我以收到恢复,我现在要开始传输数据了“
SYN这个标志位只有在TCP建立连接时才会被置1,握手完成之后被置0。
断开连接
断开连接要进行4次
A:数据传完了,可以停止了吗?
B:消息收到,但我还没有做好准备,请稍等!
B:好了,可以停止了
A:好的,过会没有消息我就关闭了。
1.当主机A完成数据传输之后,将控制位FIN置1,提出停止TCP连接的请求。
2.主机B受到FIN后对其作出响应,确认这一方向上的TCP连接将关闭,将ACK置1。
3.有B端再提出反方向的关闭请求,将FIN置1。
4.主机A对主机B的请求进行确认,将ACK置1,双方向的关闭结束。


无连接的套接字(UDP)


  • UDP是一个非连接的协议,传输数据之前源端和终端不建立连接,当它想传送时就是简单地去抓取来自应用程序的数据,并可能尽快的扔到网络上。在发送端,UDP传送数据的速度仅仅是受到应用程序生成数据的速度、计算机的能力和传输带宽的限制;在接受端,UDP把每个消息段放在队列中,应用程序每次从队列中读取一个消息。
  • 由于不需要建立连接,所以不需要维护连接状态、收发状态等,所以一台服务机可以同时象多个客户端传输相同的消息。
  • UDP信息包的标题很短,只有8个字节,相对于TCP的20个字节信息包的额外开销很小。
  • 吞吐量不受拥挤算法的调节,只受应用软件生成数据的速率传输带宽、源端和终端主机性能的限制。
  • UDP使用尽最大努力交付,即不保证可靠交付,因此主机不需要维持复杂的链接状态表。
  • UDP是面向报文的,发送方的UDP对应用程序交下来的报文再添加首部后就向下交付给IP层。即不拆分也不合并,而是保留这些报文的边界,所以应用程序需要选择合适的报文大小。

socket模块

TCP通信
服务端

import socket
from time import ctime

HOST = '172.25.254.77'
PORT = 9777

# 1. 创建服务端的socket对象
serverSocket = socket.socket()
# 2. 绑定一个ip和端口, 客户端连接时的socket;
serverSocket.bind((HOST, PORT))
# 3. 一直监听是否有客户端连接
serverSocket.listen()
print("server is listening %d......." %(PORT))
# 4. 如果有客户端连接, 接收客户端的连接;
# serverSocket.accept会返回2个值, address指的是, 客户端的ip和端口;
clientSocket, address = serverSocket.accept()

# 5. 客户端和服务端进行通信;

data = clientSocket.recv(1024).decode('utf-8')
print("接收到客户端的消息:", data)


# 6. 给客户端回复消息
clientSocket.send(b'hello client')

# 7. 关闭socket对象, 一次通信完成;
serverSocket.close()
clientSocket.close()

客户端

import socket

HOST = '172.25.254.77'
PORT = 9777
# 1.
clientSocket = socket.socket()

# 2. 连接远程主机
clientSocket.connect((HOST, PORT))

# 3. 客户端, 服务端通信
# 给server主机发送消息
clientSocket.send(b'hello server')
# 接收服务端的响应(即服务端回复的消息)
recvData = clientSocket.recv(1024).decode('utf-8')
print("接收到服务器的消息:", recvData)
# 4. 关闭socket对象:
clientSocket.close()

UDP通信
服务端

import socket


# TCP: 9999
# UDP:9999
HOST = '172.25.254.77'
PORT = 9999
server = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
# 绑定端口:
server.bind((HOST, PORT))

# 不需要调用监听方法
print('等待客户端的UDP请求.....')

while True:
    # 接收客户端的数据
    data, addr = server.recvfrom(1024)
    print("接收到客户端的信息:", data)
    print("客户端的socket地址为:", addr)

    recv_data = input("server>>").encode()
    server.sendto(recv_data, addr)

客户端

import socket

client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
address = ('172.25.254.77', 9999)

while True:
    msg = input('client>>')
    msg = msg.encode()
    client.sendto(msg, address)
    print("接收到服务端的消息:", client.recv(1024))

猜你喜欢

转载自blog.csdn.net/mashaokang1314/article/details/80754185