Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。

基于文件类型的套接字家族

套接字家族的名字:AF_UNIX

unix一切皆文件,基于文件的套接字调用的就是底层的文件系统来取数据,两个套接字进程运行在同一机器,可以通过访问同一个文件系统间接完成通信

基于网络类型的套接字家族

套接字家族的名字:AF_INET

服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束

 

socket()模块函数用法

import  socket
# socket实例类
serve=socket.socket(socket.AF_INET,socket.SOCK_STREAM)


serve.bind(('127.0.0.1',12))
# serve.bind('127.0.0.1',端口)
# 127.0.0.1这叫回送地址 表示电脑本身
# 端口 为普通整数
# 参数为一个元组


serve.listen()
# 监听

# 接收链接请求
# 第一个是表示客户端的socket 第二个客户端的地址信息
client,addr=serve.accept()

serve.recv(10)
# 接收数据 单位为字节

serve.close()
# 关闭数据

socket服务端
import socket


# 作为服务器,ip和端口号是明确的
# 参数1指定 AF_INET 为网络类型 , AF_UNIX 为文件类型
# 参数2 指定SOCK_STERAM 表示TCP协议 SOCK_DGRAM 为udp协议

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 默认就是网络类型 TCP协议
# serve = socket.socket()


server.bind(('127.0.0.1', 122))
# 开始监听1688端口
server.listen()


# 接收链接请求
# 第一个是表示客户端的socket 第二个客户端的地址信息
client,addr=server.accept()

data=client.recv(122)
client.send('222222'.encode('utf-8'))

server.close()
# 关机
socket客户端

常见的异常
服务端
import socket


client=socket.socket()


# 所有系统会自动分配随机端口给客户端

client.connect(('127.0.0.1', 122))
# 开始通话
# 发送数据 注意发送的内容只能是二进制 bytes
client.send('111111111'.encode('utf-8'))

data = client.recv(122)

client.close()
import socket
sever = socket.socket()

sever.bind(('127.0.0.1', 133))

sever.listen()

# accept 是一个阻塞函数 会一直等到有客户端链接过来 在继续执行
client,addr=sever.accept()
print('三次握手成功')

# 收发数据 注意都是用表示客户端的socket来收发数据
# client.send('hello'.encode('utf-8'))
try:
data=client.recv(100)
print('客户端发来的数据',data)
except:
print('client 下线')
client .close()
print('完成四次挥手')


# 休10秒
import time
time.sleep(10)




sever.close()
print('服务器关机')
客户端
import socket
client=socket.socket()


# connect本质实在进行三次握手 也是一个数据传输的过程 如果服务器没有立马响应 也会阻塞

client.connect(('127.0.0.1',133))

print('握手成功!')

# 发送数据 本质上是把数据交给操作系统来进行发送 一旦数据交给了操作系统 后续的发送
# 应用程序就无法控制了 ,send一般不会卡 当然 如果数据量很大就会阻塞
# client.send('hello'.encode('utf-8'))
# print('发送完成')


# 是从操作系统缓存区读取数据 如果当前还没有任何数据 就会进入阻塞
# 会一直等到有数据到来 再继续执行
try:
data=client.recv(100)
print('客户端的数据',data)
except:
print('client 下线')


# 客户端执行close 是正常关闭链接 会给服务器送空字节 用于表示要断开链接
client.close()
print('客户端关机')
import socket
server = socket.socket()

server.bind(('127.0.0.1',11))
server.listen()
server.accept()

server.close()

异常

# 如果已经开启了服务器 再次运行将会抛出 端口占用异常 把之前开启的服务器关掉即可

1.可能是由于你已经启动了服务器程序,却又再次启动了服务器程序,同一个端口不能被多个进程使用导致!

2.三次握手或四次挥手时,发生了异常导致对方程序已经结束而服务器任然处于time_wait状态导致!

3.在高并发的场景下,由于链接的客户端太多,也会产生大量处于time_wait状态的链接


"""
有些情况 明明已经关闭了进程 但是 还是端口占用
可能是进程正在后台运行 可以通过端口查出进程 进行关闭
windows下
netstat -ano | findstr 9898
tasklist | findstr 进程id 拿到进程名称
taskkill /f /t /im 进程名称
大招: 重启电脑
"""
循环
服务器
import socket
sever = socket.socket()
# 指定服务器的端口和ip 客户端的端口系统自动分配的
sever.bind(('127.0.0.1',36))
sever.listen()


while True:
client_socket,client_addr=sever.accept()
buffer_size=1024
# 缓冲区  就是一个临时的容器  

while True:
try:
data=client_socket.recv(1024)
if not data:
client_socket.close()
break

print(data.decode('utf-8'))
# 解码时必须保证双方同意编码方式
# 转为大写在发回去
client_socket.send(data.upper())
except ConnectionResetError as a:
print('%s %s" % (client_addr[0],client_addr[1]),e')
# 如果对方下线了 那服务器也应该关闭对应的客户端对象
client_socket.close()
break

客户端
import  socket

client=socket.socket()
client .connect(('127.0.0.1',36))


while True:
msg=input('输入内容...')
if msg == 'q':
break
if not msg:
continue
client.send(msg.encode('utf-8'))
print('发送')
data = client.recv(1024)
print(data.decode('utf-8'))

client.close()

windows正常关闭
服务器
import socket
sever = socket.socket()

sever.bind(('127.0.0.1',96))
sever.listen()

while True:
client_socket,client_addr=sever.accept()
buffer_size=1024

while True:
try:

data=client_socket.recv(1024)
if not data:
print(data)

break

print('收到数据...',data.decode('utf-8'))
# 解码时必须保证双方同意编码方式
# 转为大写在发回去
client_socket.send(data.upper())
except ConnectionResetError as a:
print('%s %s'%(client_addr[0],client_addr[1]),a)
# 如果对方下线了 那服务器也应该关闭对应的客户端对象
break

client_socket.close()
客户端

import socket
client=socket.socket()

client.connect(('127.0.0.1',96))


# 添加循环 用来重复收发数据

while True:
# 收发的顺序 必须和对面相反 否则卡死了
msg= input('输入内容....q 退出')
if msg == 'q':
break
if not msg:
continue
client.send(msg.encode('utf-8'))
print('发送')
data = client.recv(1024)
print(data.decode('utf-8'))
client.close()











 

posted on 2019-05-28 22:28  我只想你  阅读(527)  评论(0编辑  收藏  举报