在这片博文我们将使用python完成一个hello/hi的简单的网络聊天程序
先做一下准备工作
1.linux的socket基础api:
使用socket()创建套接字
int socket(int af, int type, int protocol); af为IP地址类型,AF_INE和AF_INET6分别对应ipv4和ipv6地址type是数据传输方式,Sock_stream(面向连接套接字)和sock_dgram(无连接套接字)protocol是传输协议,IPPROTO_TCP和IPPROTO_UDP 使用bind()将套接字与特定的ip地址和端口号绑定
int bind(int sock, struct sockaddr *addr, socklen_t addrlen);
sock 为 socket 文件描述符,addr 为 sockaddr 结构体变量的指针,addrlen 为 addr 变量的大小 客户端使用connect()建立连接
int connect(int sock, struct sockaddr *serv_addr, socklen_t addrlen);
使用listen()函数让套接字进入被动监听状态int listen(int sock, int backlog)sock 为需要进入监听状态的套接字,backlog 为请求队列的最大长度。 使用 write() 可以向套接字中写入数据
ssize_t write(int fd, const void *buf, size_t nbytes)fd 为要写入的文件的描述符,buf 为要写入的数据的缓冲区地址,nbytes 为要写入的数据的字节数
使用 read() 可以从套接字中读取数据
ssize_t read(int fd, void *buf, size_t nbytes);
fd 为要读取的文件的描述符,buf 为要接收数据的缓冲区地址,nbytes 为要读取的数据的字节数
2.python中相关的库
2.1socket库:这是python提供的基本的 低级别的网络服务,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口的全部方法
我们用 socket()函数来创建套接字,语法格式如下:
socket.socket([family[, type[, proto]]])
通过调用底层socket接口,提供有一下方法:
s.bind() | 绑定地址(host,port)到套接字, 在AF_INET下,以元组(host,port)的形式表示地址。 |
s.listen() | 开始TCP监听。backlog指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5就可以了。 |
s.accept() | 被动接受TCP客户端连接,(阻塞式)等待连接的到来 |
客户端套接字 | |
s.connect() | 主动初始化TCP服务器连接,。一般address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。 |
s.connect_ex() | connect()函数的扩展版本,出错时返回出错码,而不是抛出异常 |
公共用途的套接字函数 | |
s.recv() | 接收TCP数据,数据以字符串形式返回,bufsize指定要接收的最大数据量。flag提供有关消息的其他信息,通常可以忽略。 |
s.send() | 发送TCP数据,将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。 |
2.2 threading库:
接受和发送消息的方法都是阻塞的,客户端和服务端之间要进行正常聊天,需要一个线程来接受对方的消息,另一个线程来发送消息,
通过python的threading库来实现这个功能,示例如下:
t=threading.Thread(target=tcp_recv, args=(s, addr))
t.start()
3. 实现hello/hi的简单的网络聊天程序的python代码
客户端:
import socket
import threading
import time
from time import strftime, localtime
#定义套接字
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 建立连接:
addr=(‘127.0.0.1‘, 9999)
s.connect(addr)
def tcp_recv(s,addr):
while True:
print(strftime("%Y-%m-%d %H:%M:%S", localtime()),s.recv(1024).decode(‘utf-8‘))
t=threading.Thread(target=tcp_recv, args=(s, addr))
t.start()
while True:
msg=input()
# 发送数据:
s.send((‘ From client : %s‘% msg).encode(‘utf-8‘))
if msg ==‘exit‘:
break
s.send(b‘exit‘)
s.close()
服务端:
import threading
import socket
from time import strftime, localtime
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((‘127.0.0.1‘, 9999))
s.listen(5)
print(‘Waiting for connection...‘)
def tcp_recv(sock, addr):
while True:
data = sock.recv(1024)
if not data or data.decode(‘utf-8‘) == ‘exit‘:
break
print(strftime("%Y-%m-%d %H:%M:%S", localtime()),data.decode(‘utf-8‘))
#sock.send((‘Server:%s‘% input()).encode(‘utf-8‘))
sock.close()
print(‘Connection from %s:%s closed.‘ % addr)
def tcp_send(sock):
while True:
msg = input()
if msg == ‘exit‘:
exit
#print(‘Client:%s‘%data.decode(‘utf-8‘))
sock.send((‘ From server : %s‘% msg).encode(‘utf-8‘))
print(‘Connection from %s:%s closed.‘ % addr)
sock, addr = s.accept()
print(‘Accept new connection from %s:%s...‘ % addr)
sock.send(b‘ From server : Welcome!‘)
while True:
# 接受一个新连接:
# 创建新线程来处理TCP连接:
t = threading.Thread(target=tcp_recv, args=(sock, addr))
t.start()
tcp_send(sock)
打开两个终端运行serve.py 和 client.py,运行结果应该是这样的:
服务端:
客户端:
原文地址:https://www.cnblogs.com/ustczjce/p/12024085.html