9. socket编程

1. HTTP、Socket、TCP

网络模型和协议位置:



1. socket 不属于任何协议,可以看作操作系统给的api。 通过socket我们可以利用TCP和UDP协议。比如QQ就是利用socket自己构建一套应用层协议,来实现聊天功能的。
2. http实现不了双向, 比如网站的聊天功能利用websocket协议, http实现不了这样的功能。

2. 利用socket 实现client和server通讯

socket编程流程(左侧server端,右侧client端):




http:   三次握手后,recvsendclose了。下次通讯又得三次握手。显然不满足我们聊天功能的需求。
实时聊天: 三次握手不断开, 不断重复recvsend

代码实现server和client通信

server:

import socket

# AF_INET ip4网络    SOCK_STREAM 表示tcp
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('0.0.0.0', 8000))
server.listen()
sock, addr = server.accept()

# 获取从客户端发送的数据
data = sock.recv(1024)   # 一次获取1024字节  1k的数据
print(data.decode('utf8'))
sock.send('hello back'.encode('utf8'))
server.close()
sock.close()

client:

import socket
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('0.0.0.0', 8000))
client.send('hello'.encode('utf8'))
data = client.recv(1024)
print(data.decode('utf8'))
client.close()


3. socket 实现聊天功能和多用户连接

1. 先实现单对单聊天

server:

import socket

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('0.0.0.0', 5000))
server.listen()
sock, addr = server.accept()

while True:
    data = sock.recv(1024)      # serverrecvsend
    print(data.decode('utf8'))
    re_data = input()
    sock.send(re_data.encode('utf8'))

client:

扫描二维码关注公众号,回复: 1644187 查看本文章
import socket
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('0.0.0.0', 5000))
while True:
    re_data = input()
    client.send(re_data.encode('utf8'))   # clinet端先sendrecv
    data = client.recv(1024)   
    print(data.decode('utf8'))

2. 实现多人聊天

server:

import socket
import threading

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('0.0.0.0', 6000))
server.listen()


def handle_sock(sock, addr):
    while True:
        data = sock.recv(1024)      
        message = data.decode('utf8')
        print(message)
        if message == 'exit':    # client 发送exit时, 连接断开
            break
        re_data = input()
        sock.send(re_data.encode('utf8'))
    sock.close()


while True:
    sock, addr = server.accept()

    # 用线程处理新的用户连接
    client_thread = threading.Thread(target=handle_sock, args=[sock, addr])
    client_thread.start()

client:

import socket
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('0.0.0.0', 6000))
while True:
    re_data = input()
    client.send(re_data.encode('utf8'))  
    data = client.recv(1024)   
    print(data.decode('utf8'))

4. socket 模拟http请求

以get百度为例子:

import socket
from urllib.parse import urlparse


def get_url(url):
    # 通过socket请求html
    url = urlparse(url)
    host = url.netloc     # www.baidu.com
    path = url.path
    if path == "":
        path = '/'

    # 建立socket连接
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client.connect((host, 80))

    client.send(
        "GET {} HTTP/1.1\r\nHost:{}\r\nConnection:close\r\n\r\n".format(path, host).encode('utf8'))
    data = b""
    while True:
        d = client.recv(1024)
        if d:
            data += d
        else:
            break

    data = data.decode('utf8')
    html_data = data.split('\r\n\r\n')[1]  # 把请求头信息去掉, 只要网页内容
    print(html_data)
    client.close()


if __name__ == '__main__':
    get_url('http://www.baidu.com')

猜你喜欢

转载自blog.csdn.net/weixin_41207499/article/details/80567118