网络编程:
网络通信三要素:IP地址(127.0.0.1:回环地址,保留地址,可用于简单的测试网卡是否有效,表示本机),端口号,传输协议
socket编程:
#family type
SOCK_STREAM:tcp
SOCK_DGRAM:udp

#family=AF_INET:服务器之间的通信IP v4
#family=AF_INET6:服务器之间的通信IP v6
#family=AF_UNIX:unix不同进程之间的通信

server下的方法:
bind()
listen()
accept()
send()
sendall()
recv()
close()

client下的方法:
connect()
send()
sendall()
recv()
close()
传送和接收的内容是byte类型,必须是一收一发,否则会导致发送的数据没有收到

在python中有两种类型,str和bytes
str:unicode编码的称为str类型
bytes:十六进制
由str到bytes叫编码
由bytes到str叫解码

简单的服务器和客户之间的通信:

server:服务端
import socket
sk=socket.socket() #sk是建立连接用的,sk是socket对象
print(sk)
address=('127.0.0.1',8000)
sk.bind(address) #参数必须是元祖,绑定
sk.listen(3) #参数为排队的个数
print('waiting....')
conn,addr=sk.accept()
print(conn)
# inp=input('>>>')
# conn.send(bytes(inp,'utf8'))

data=conn.recv(1024)
print(str(data,'utf8'))

conn.close()

client:客户端
import socket
sk=socket.socket()
address=('127.0.0.1',8000)
sk.connect(address)
# data=sk.recv(1024) #阻塞
# print(str(data,'utf8'))

data=sk.send(bytes('博客','utf8'))
# print(str(data,'utf8'))
sk.close()
不间断的通信:
server:服务器端
import socket
sk=socket.socket()
print(sk)
address=('127.0.0.1',8000)
sk.bind(address)
sk.listen(3)
print('waiting......')
while 1:
conn,addr=sk.accept()
print(addr)
while 1:
try:
data=conn.recv(1024)
except Exception :
break
print('........',str(data,'utf8'))
if not data:break
inp=input('>>>')
conn.send(bytes(inp,'utf8'))

sk.close()

client:客户端

import socket
sk=socket.socket()
print(sk)
address=('127.0.0.1',8000)
sk.connect(address)
while True:
inp=input('>>>')
if inp=='exit':
break
sk.send(bytes(inp,'utf8'))
data=sk.recv(1024)
print(str(data,'utf8'))

sk.close()

命令编程:
server:服务器端
import socket
import subprocess

sk=socket.socket()
print(sk)
address=('127.0.0.1',8000)
sk.bind(address)
sk.listen(3)
print('waiting......')
while 1:
conn,addr=sk.accept()
print(addr)
while 1:
try:
data=conn.recv(1024)
except Exception :
break
if not data:break
print('........',str(data,'utf8'))
obj=subprocess.Popen(str(data,'utf8'),shell=True,stdout=subprocess.PIPE)
cmd_result=obj.stdout.read() #cmd_result类型是bytes,Windows默认是gbk编码

result_len=bytes(str(len(cmd_result)),'utf8')
conn.sendall(result_len) #粘包现象
conn.recv(1024) #粘报包的解决办法,隔开
conn.sendall(cmd_result)
sk.close()

client:客户端
import socket
sk=socket.socket()
print(sk)
address=('127.0.0.1',8000)
sk.connect(address)
while True:
inp=input('>>>')
if inp=='exit':
break
sk.send(bytes(inp,'utf8'))
result_len=int(str(sk.recv(1024),'utf8'))
sk.sendall(bytes(str('ok'),'utf8'))
print(result_len)
data=bytes()
while len(data)!=result_len:
recv=sk.recv(1024) #不能超过8k,重复接收
data+=recv
print(str(data,'gbk'))

sk.close()

文件上传:
server:服务器端
import socket
import subprocess
import os
sk=socket.socket()
print(sk)
address=('127.0.0.1',8000)
sk.bind(address)
sk.listen(3)
print('waiting......')
BASE_DIR=os.path.dirname(os.path.abspath(__file__))
while 1:
conn,addr=sk.accept()

while 1:
data=conn.recv(1024)
cmd,filename,filesize=str(data,'utf8').split('|')
path=os.path.join(BASE_DIR,'file',filename)
filesize=int(filesize)

f=open(path,'wb')
has_recv=0
while has_recv!=filesize:
data=conn.recv(1024)
f.write(data)
has_recv+=len(data)
f.close()

sk.close()

client:客户端
import socket
import os
sk=socket.socket()
print(sk)
address=('127.0.0.1',8000)
sk.connect(address)
BASE_DIR=os.path.dirname(os.path.abspath(__file__))
while True:
inp=input('>>>').strip() #post|file.png
cmd,path=inp.split('|')
path=os.path.join(BASE_DIR,path)
filename=os.path.basename(path)
file_size=os.stat(path).st_size
file_info='post|%s|%s'%(filename,file_size)
sk.sendall(bytes(file_info,'utf8'))

f=open(path,'rb')
has_sent=0
while has_sent!=file_size:
data = f.read(1024)
sk.sendall(data)
has_sent+=len(data)
f.close()
print('上传成功')

sk.close()