史上最全socket模块详解!没有学不会的模块!只有学不学的模块!

史上最全socket模块详解!没有学不会的模块!只有学不学的模块!

史上最全socket模块详解!没有学不会的模块!只有学不学的模块!

import socket

sk= socket.socket()#创建对象

sk.bind(('127.0.0.1',9999,))#绑定IP和端口,以一个元组的方式传进去

sk.listen(5)#在前面链接已经建立的情况下,后面最多让五个人等待

while True:#让服务器端处于可以永远处于接受客户端请求的状态

conn,address=sk.accept()

print(conn,address)

私信菜鸟 007 获取最全教程合集!

史上最全socket模块详解!没有学不会的模块!只有学不学的模块!

obj.connect(('127.0.0.1',9999,))#链接服务端

obj.close()#链接之后关闭

我们先让服务器端启动,然后再启动客户端,结果如图所示

史上最全socket模块详解!没有学不会的模块!只有学不学的模块!

<socket.socket fd=4, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 36126)> ('127.0.0.1', 36126)

<socket.socket fd=5, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 36128)> ('127.0.0.1', 36128)

<socket.socket fd=4, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 36130)> ('127.0.0.1', 36130)

成功打印出了每次的链接,以及客户端的IP以及端口号

(2)基于socket实现简单的传送消息

#服务器端

import socket

sk= socket.socket()

sk.bind(('127.0.0.1',9999,))#绑定IP和端口,以一个元组的方式传进去

sk.listen(5)#在前面链接已经建立的情况下,后面最多让五个人等待

while True:#让服务器端处于可以永远处于接受客户端请求的状态

conn,address=sk.accept()#基于conn这个链接发送东西

conn.sendall(bytes('有空来Linux公社www.linuxidc.com天天给你新知识',encoding='utf-8'))#Python3要用bytes类型,发送字节

'''建立一次链接,服务器就发送这个字段'''

print(conn,address)

然后用是客户端代码

#客户端

import socket

obj =socket.socket()

'''相对于客户端,制定要链接谁就好了

'''

obj.connect(('127.0.0.1',9999,))#链接服务端

'''

客户端去链接服务端,如果服务器端没有返回消息给客户端,则客户端会一直

在recv状态,一直等待服务器的消息

'''

result1= obj.recv(2014)#表示最多接收1024个字节,超过了下次接收、

result2= str(result1,encoding='utf-8')

print(result2)

obj.close()#链接之后关闭

当启动一次客户端建立一次链接,就会收到消息,结果如图

史上最全socket模块详解!没有学不会的模块!只有学不学的模块!

(3)基于socket实现聊天机器人

#服务器端

import socket

sk= socket.socket()

sk.bind(('127.0.0.1',9999,))#绑定IP和端口,以一个元组的方式传进去

sk.listen(5)#在前面链接已经建立的情况下,后面最多让五个人等待

while True:#让服务器端处于可以永远处于接受客户端请求的状态

conn,address=sk.accept()#基于conn这个链接发送东西

conn.sendall(bytes('你好www.linuxidc.com,链接已经建立',encoding='utf-8'))#Python3要用bytes类型,发送字节

# '''建立一次链接,服务器就先发送这个字段'''

while True:#让通信状态不中断

ret_bytes = conn.recv(1024)

ret_str = str(ret_bytes,encoding='utf-8')

if ret_str =='q':#如果收到q,则终止链接

break

conn.sendall(bytes(ret_str+' 已收到该信息',encoding='utf-8'))

#print(conn,address)

下面是客户端代码

#客户端

import socket

obj =socket.socket()

'''相对于客户端,制定要链接谁就好了

'''

obj.connect(('127.0.0.1',9999,))#链接服务端

'''

客户端去链接服务端,如果服务器端没有返回消息给客户端,则客户端会一直

在recv状态,一直等待服务器的消息

'''

result1= obj.recv(2014)#表示最多接收1024个字节,超过了下次接收、

result2= str(result1,encoding='utf-8')

print(result2)

while True:

data = input('请输入你要发送的内容:')

if data == 'q':

obj.sendall(bytes(data, encoding='utf-8'))

print('链接断开')

break

else:

obj.sendall(bytes(data,encoding='utf-8'))

rec_byte = obj.recv(1024)#发了之后,接收信息

rec_str = str(rec_byte,encoding='utf-8')

print(rec_str)

obj.close()#链接之后关闭

结果如图所示

史上最全socket模块详解!没有学不会的模块!只有学不学的模块!

(4)利用socket传送图片文件

#服务器端

import socket

sk= socket.socket()

sk.bind(('127.0.0.1',9999,))#绑定IP和端口,以一个元组的方式传进去

sk.listen(5)#在前面链接已经建立的情况下,后面最多让五个人等待

while True:#

conn,address= sk.accept()

conn.sendall(bytes('链接已建立,可以发送数据了',encoding='utf-8'))

file_size = str(conn.recv(1024),encoding='utf-8')#接收文件大小

print('接收的文件字节数:'+file_size)

total_size = int(file_size)

has_recv = 0#默认已接收了0个字节

f = open('linuxidc.com.png','wb')

#先接收文件大小,再开始接收文件

while True:

if total_size ==has_recv:#如果已接收的文件大小与客户端发送的一样大,则表示已经接收完毕

break

data = conn.recv(1024)

f.write(data)

has_recv +=len(data)

print('文件接收成功')

f.close()

下面是客户端

#客户端

import os

import socket

obj =socket.socket()

obj.connect(('127.0.0.1',9999,))#链接服务端

'''

客户端去链接服务端,如果服务器端没有返回消息给客户端,则客户端会一直

在recv状态,一直等待服务器的消息

# '''

#obj.sendall(bytes('你好',encoding='utf-8'))

ret_bytes = obj.recv(1024)

ret_str = str(ret_bytes,encoding='utf-8')

print(ret_str)

#发送文件大小

size=os.stat('linuxidc.png').st_size#获取文件大小

obj.sendall(bytes(str(size),encoding='utf-8'),)#文件大小的int型,要先转化为字符串

with open('linuxidc.png','rb')as f:

for line in f:

obj.sendall(line)

obj.close()

结果如图

进群:960410445  即可获取源码!

史上最全socket模块详解!没有学不会的模块!只有学不学的模块!

(5)socket粘包问题

发送文件需要依赖双方的缓冲区,就是我们先把文件写到缓冲区,然后再发送过去,但是我们一般不知道什么时候发过去,这容易造成粘包问题。例如上面的例子,客户端先发送文件大小,然后读文件写进缓冲区,假如文件读取特别快,第一次发送过去的可能既有文件大小又有文件内容,造成错误,这叫粘包,简而言之就是收到的信息比原本应收的多。

那么怎么解决粘包问题呢,通过发送以及接收确认包,还是以上面的例子说明,客户在发送文件大小之后不要马上发送文件,先recv接收一下,等待服务器发送已收到文件大小的确认包之后,再读取文件、发送文件,这样文件的发送和之前数据的发送就

完全独立开来了。

#服务器端

import socket

sk= socket.socket()

sk.bind(('127.0.0.1',9999,))#绑定IP和端口,以一个元组的方式传进去

sk.listen(5)#在前面链接已经建立的情况下,后面最多让五个人等待

while True:#

conn,address= sk.accept()

conn.sendall(bytes('链接已建立,可以发送数据了',encoding='utf-8'))

file_size = str(conn.recv(1024),encoding='utf-8')#接收文件大小

print('接收的文件字节数:'+file_size)

total_size = int(file_size)

has_recv = 0#默认已接收了0个字节

conn.sendall(bytes('文件大小已收到,可以开始发送数据了',encoding='utf-8'))#解决粘包问题,已经收到了文件大小,后面就可以单独发文件了

f = open('linuxidc.com.png','wb')

#先接收文件大小,再开始接收文件

while True:

if total_size ==has_recv:#如果已接收的文件大小与客户端发送的一样大,则表示已经接收完毕

break

data = conn.recv(1024)

f.write(data)

has_recv +=len(data)

print('文件接收成功')

f.close()

下面是客户端

#客户端

import os

import socket

obj =socket.socket()

obj.connect(('127.0.0.1',9999,))#链接服务端

'''

客户端去链接服务端,如果服务器端没有返回消息给客户端,则客户端会一直

在recv状态,一直等待服务器的消息

# '''

#obj.sendall(bytes('你好www.linuxidc.com',encoding='utf-8'))

ret_bytes = obj.recv(1024)

ret_str = str(ret_bytes,encoding='utf-8')

print(ret_str)

#发送文件大小

size=os.stat('linuxidc.png').st_size#获取文件大小

obj.sendall(bytes(str(size),encoding='utf-8'),)#文件大小的int型,要先转化为字符串

ack_packet=obj.recv(1024)

print(str(ack_packet,encoding='utf-8'))

with open('linuxidc.png','rb')as f:

for line in f:

obj.sendall(line)

obj.close()

史上最全socket模块详解!没有学不会的模块!只有学不学的模块!

猜你喜欢

转载自blog.csdn.net/qq_42156420/article/details/85680634