socket套接字开篇
socket套接字:
Socket是应用层与TCPIP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
也有人说socket就是以IP+port的一种组合,通过两者结合完成了定位世界上唯一一台主机的应用程序的定位。
套接字起源于 20 世纪 70 年代加利福尼亚大学伯克利分校版本的 Unix,即人们所说的 BSD Unix。 因此,有时人们也把套接字称为“伯克利套接字”或“BSD 套接字”。一开始,套接字被设计用在同 一台主机上多个应用程序之间的通讯。这也被称进程间通讯,或 IPC。套接字有两种(或者称为有两个种族),分别是基于文件型的和基于网络型的。
套接字中基于文件类型的家族:
AF_UNIX:两个套接字进程运行在同一机器,可以通过访问同一个文件系统间接完成通信
套接字中基于网络的家族:
AF_INET:运行在两台机器的进程,根据互联网协议来进行通信
套接字工作流程:
根据TCP协议的传输我们有两个目标,客户端和服务端
我们先来看客户端,首先我们假设已经得到了数据,所以先调用socket套接字对象,得到对象之后我们需要调用传输层,先建立TCP连接connect()接口,通过调用接口后我们得到一个对象,通过调用对象下的方法发送数据和接受数据。
最后在关闭该链接。
同时我们再来看服务端,首先也是要根据协议来调用socket接口,然后要使用bind绑定一个端口号,这样我们就获得了一个固定的且唯一的位置,接下来定义半链接池的大小,之后从半链接池中取出链接请求完成链接,通过调用接口后我们得到一个对象,通过调用对象下的方法发送数据和接受数据。
最后在关闭该链接。
我们为什么需要固定服务端位置而不是客户端呢?
我们可以进行一个思考,如果我们访问的网站每天位置都在变化,用户体验是如何的呢?由此我们得出结论服务端的位置要固定,那客户端呢,我们的ip是自动获取的同时考虑到高并发的情况客户端不能同时也不应该写死。
tcp协议简单完成
服务端
import socket
import subprocess
sever = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sever.bind(("127.0.0.1",8080))
sever.listen(5)
while True:
conn,addr = sever.accept()
while True:
try:
data = conn.recv(1024)
if len(data) == 0:break
print(data.decode("utf-8"))
conn.send(
data.upper()
)
except Exception as err:
print(err)
break
conn.close()
tcp协议简单完成
客户端
import socket
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(("127.0.0.1",8080))
while True:
msg = input("输入命令")
if len(msg) == 0:continue
if msg != "q":
client.send(msg.encode("utf-8"))
data = client.recv(1024)
print(data)
else:
break
client.close()
udp协议简单完成
服务端
import socket
sever = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
sever.bind(("127.0.0.1",8080))
while True:
data,addr = sever.recvfrom(1024)
print(data.decode("utf-8"))
sever.sendto(data.upper(),addr)
udp协议简单完成
客户端
import socket
client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
while True:
data = input("输入信息")
client.sendto(data.encode('utf-8'),("127.0.0.1",8080))
msg,addr = client.recvfrom(1024)
print(msg)
tcp完成远程传输指令
服务端
import socket
import subprocess
sever = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sever.bind(("127.0.0.1",8082))
sever.listen(5)
while True:
conn,addr = sever.accept()
while True:
try:
data = conn.recv(1024)
if len(data) == 0:break
res = subprocess.Popen(data.decode("gbk"),
shell = True,
stdout=subprocess.PIPE,
stderr = subprocess.PIPE)
stdout = res.stdout.read()
stderr = res.stderr.read()
conn.send(stdout)
conn.send(stderr)
except Exception as err:
print(err)
break
conn.close()
客户端
import socket
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(("127.0.0.1",8082))
while True :
cmd = input("输入命令")
if not cmd :continue
client.send(cmd.encode("gbk"))
res = client.recv(1024)
print(res.decode("gbk"))
client.close()
udp简单聊天室实现
import socket
ip_port = ('127.0.0.1', 8081)
udp_server_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 买手机
udp_server_sock.bind(ip_port)
while True:
qq_msg, addr = udp_server_sock.recvfrom(1024)
print('来自[%s:%s]的一条消息:\033[1;44m%s\033[0m' % (addr[0], addr[1], qq_msg.decode('utf-8')))
back_msg = input('回复消息: ').strip()
udp_server_sock.sendto(back_msg.encode('utf-8'), addr)
客户端1
import socket
BUFSIZE=1024
udp_client_socket=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
qq_name_dic={
'狗哥alex':('127.0.0.1',8081),
'瞎驴':('127.0.0.1',8081),
'一棵树':('127.0.0.1',8081),
'武大郎':('127.0.0.1',8081),
}
while True:
qq_name=input('请选择聊天对象: ').strip()
while True:
msg=input('请输入消息,回车发送: ').strip()
if msg == 'quit':break
if not msg or not qq_name or qq_name not in qq_name_dic:continue
udp_client_socket.sendto(msg.encode('utf-8'),qq_name_dic[qq_name])
back_msg,addr=udp_client_socket.recvfrom(BUFSIZE)
print('来自[%s:%s]的一条消息:\033[1;44m%s\033[0m' %(addr[0],addr[1],back_msg.decode('utf-8')))
udp_client_socket.close()
客户端2
__author__ = 'Linhaifeng'
import socket
BUFSIZE=1024
udp_client_socket=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
qq_name_dic={
'狗哥alex':('127.0.0.1',8081),
'瞎驴':('127.0.0.1',8081),
'一棵树':('127.0.0.1',8081),
'武大郎':('127.0.0.1',8081),
}
while True:
qq_name=input('请选择聊天对象: ').strip()
while True:
msg=input('请输入消息,回车发送: ').strip()
if msg == 'quit':break
if not msg or not qq_name or qq_name not in qq_name_dic:continue
udp_client_socket.sendto(msg.encode('utf-8'),qq_name_dic[qq_name])
back_msg,addr=udp_client_socket.recvfrom(BUFSIZE)
print('来自[%s:%s]的一条消息:\033[1;44m%s\033[0m' %(addr[0],addr[1],back_msg.decode('utf-8')))
udp_client_socket.close()