Python 之Socket编程

#######Socket编程########

## 网络通讯的三大要素

# 网络间实现通信的三大要素分别是:IP地址、port端口以及通信协议(TCP/UDP)

## IP
- Mac地址
- 分类:
        IPv4: 172.25.254.100  ===> 32位的二进制格式, 点分十进制法; 2^32-1
        IPv6:  ===> 128位的二进制格式 , 冒分十六进制;
- 查看:
    ip addr show br0

## port端口: 为了标识通信的应用程序

     注:常见的port和服务的对应关系:/etc/services
             已经被分配的port: 0-1024
             自定义端口号的范围: 1024-65535

## 通信协议: TCP和UDP协议

## Socket编程

# socket: 其实就是 IP:port 的组成

import socket

print(socket.gethostname())
# 'www.baiu.com'根据域名获取对应服务器的ip地址
print(socket.gethostbyname("www.baidu.com"))
# 根据IP获取对应的主机名
print(socket.gethostbyaddr("172.25.254.40"))

print(socket.getaddrinfo("www.xunlei.com", 80))
#注:
# AddressFamily.AF_INET  : ipv4
# socket.AF_INET6  : ipv6

# SOCK_STREAM: TCP协议
# socket.SOCK_DGRAM: UDP协议

## 应用实例:

               编写一个脚本, 捉取www.xunlei.com这个域名对应的IPv4的地址

import socket

print(socket.getaddrinfo("www.xunlei.com", 80))
# [(<AddressFamily.AF_INET: 2>, <SocketKind.SOCK_STREAM: 1>, 6, '', ('183.60.209.24', 80)), (<AddressFamily.AF_INET: 2>,
# 显示出的地址信息其实就是列表中嵌套元祖

Addrinfo = socket.getaddrinfo("www.xunlei.com", 80)
Addlist = [str(ip) for item in Addrinfo for ip in item[4]]
print(Addlist)
list = [i for i in Addlist if '.' in i]
print(list)

## Socket 实现Web简易服务器

import socket

def handle_request(sockObj):
    #HTTP/1.1时HTTP的版本
    sockObj.send(b'HTTP/1.1  200 OK \r\n\r\n')
    with open('hello.html') as f:
        sockObj.send(f.read().encode('utf-8'))

if __name__ == "__main__":
    #创建一个socket对象
    """
    class socket(_socket.socket):

    __slots__ = ["__weakref__", "_io_refs", "_closed"]

    def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None):
        # For user code address family and type values are IntEnum members, but
        # for the underlying _socket.socket they're just integers. The
        # constructor of _socket.socket converts the given argument to an
        # integer automatically.
        _socket.socket.__init__(self, family, type, proto, fileno)
        self._io_refs = 0
        self._closed = False
    """
    server = socket.socket()
    #绑定IP端口
    """
    Bind the socket to a local address.  For IP sockets, the address is a
        pair (host, port); the host must refer to the local host. For raw packet
        sockets the address is a tuple (ifname, proto [,pkttype [,hatype]])
    """
    server.bind(('172.25.254.40', 9002))
    # 监听是否有用户连接
    server.listen(3)
    print("服务器端已经启动9002端口......")

    while True:
        #  接受客户端连接
        """
        accept() -> (socket object, address info)
        """
        sockObj, address = server.accept()
        # 接受客户端发送的消息 1024个字符
        recv_data = sockObj.recv(1024)
        # 与客户端进行交互, 返回给客户端信息
        handle_request(sockObj)
        sockObj.close()

## TCP聊天室

# 创建TCP聊天室的服务端

import socket

server = socket.socket()
server.bind(("172.25.254.40", 9005))
server.listen()
sockObj, address = server.accept()
print(sockObj)
print(address)
while True:
    #接收客户端发送的消息
    data = sockObj.recv(1024).decode('utf-8')
    print("client:%s" %data)
    if data == 'quit':
        break
    # 给客户端回复消息
    send_data = input("server:")
    if send_data == 'quit':
        break
    sockObj.send(send_data.encode('utf-8'))
sockObj.close()
server.close()

# 创建TCP聊天室的客户端

import socket

HOST = '172.25.254.40'
PORT = 9005
client = socket.socket()
client.connect((HOST, PORT))
while True:
    send_data = input("client:")
    client.send(send_data.encode('utf-8'))
    if send_data == 'quit':
        break
    data = client.recv(1024).decode('utf-8')
    if data == 'quit':
        break
    print("server:%s" % data)

client.close()

## 运行的聊天结果

#服务端

#客户端

## 拓展:利用协程实现多客户端聊天

# 服务端:

import socket
from gevent import monkey

monkey.patch_all()
import gevent


def handle_request(sockObj):
    while True:
        # 接收客户端发送的消息
        data = sockObj.recv(1024).decode('utf-8')
        print("client:%s" % data)
        if data == 'quit':
            break
        # 给客户端回复消息
        send_data = input("server:")
        if send_data == 'quit':
            break
        sockObj.send(send_data.encode('utf-8'))


server = socket.socket()
server.bind(("172.25.254.40", 9005))
server.listen()
print("服务器端已经启动")
while True:
    # 接受客户端连接
    sockObj, address = server.accept()
    # handle_request(sockObj)
    gevent.spawn(handle_request, sockObj)

sockObj.close()
server.close()

# 客户端

import socket

HOST = '172.25.254.40'
PORT = 9005
client = socket.socket()
client.connect((HOST, PORT))
while True:
    send_data = input("client:")
    client.send(send_data.encode('utf-8'))
    if send_data == 'quit':
        break
    data = client.recv(1024).decode('utf-8')
    if data == 'quit':
        break
    print("server:%s" % data)

client.close()

## 获取网页内容

import socket
from urllib.request import urlopen

client = socket.socket()
client.connect(('www.baidu.com', 80))
client.send(b'GET / HTTP/1.1\r\nHost: www.baidu.com\r\nConnection: close\r\n\r\n')
recv_data = client.recv(1024*100)
print(recv_data.decode('utf-8'))
client.close()

# 运行结果:

## UDP 聊天室

# UDP聊天室服务端

import socket

# 由于创建socket对象时默认参数是TCP协议,需要进行参数修改
server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(("172.25.254.40", 6003))
print("等待客户端UDP请求")
while True:
    data, address = server.recvfrom(1024)
    if data == 'quit':
        break
    print("client:%s" % data.decode('utf-8'))
    # print("客户端连接的socket地址:%s" % address)
    send_data = input("server:")
    if send_data == 'quit':
        break
    server.sendto(send_data.encode('utf-8'), address)
    server.close()

# UDP聊天室客户端

import socket

HOST = '172.25.254.40'
PORT = 6003

client = socket.socket(type=socket.SOCK_DGRAM)
while True:
    send_data = input("client:")
    if send_data == 'quit':
        break
    client.sendto(send_data.encode('utf-8'), (HOST, PORT))
    data, address = client.recvfrom(1024).decode('utf-8')
    if data == 'quit':
        break
    print("server:%s" % data)
    client.close()

###################################

猜你喜欢

转载自blog.csdn.net/houzeyu666/article/details/82863134