Socket

TCP/IP:(通信)
tcp/ip协议是主机接入互联网以及接入换联网的两台主机通信的标准

实例:

  

import socket
ip_port=('127.0.0.1',9999)
#买手机
s=socket.socket()

#拨号
s.connect(ip_port)

while True:
#发消息
send_data=input(">>:")
if send_data == '':continue
s.send(bytes(send_data,encoding='utf8'))
if send_data == 'e':break
#收消息
recv_data=s.recv(1024)
#挂电话
s.close()

socket _client
socket_client
import socket
ip_port=('127.0.0.1',9999)
#买手机
s=socket.socket()
#买卡
s.bind(ip_port)
#开机
s.listen(5)
#待机
conn,aad=s.accept()
while True:
    try:
        #收消息
        recv_data=conn.recv(1024)
        if str(recv_data,encoding='utf8') == 'e':break
        print(str(recv_data,encoding='utf8'))
        #发消息
        send_data=recv_data
        conn.send(send_data)
    except Exception:
        break
#挂电话
conn.close()
socket_server

 

单线程:

import socket
ip_port=('127.0.0.1',9999)
#买手机
s=socket.socket()
#买卡
s.bind(ip_port)
#开机
s.listen(1)  #连接数
while True:
    #待机
    conn,aad=s.accept()
    while True:
        try:
            #收消息
            recv_data=conn.recv(1024)
            if str(recv_data,encoding='utf8') == 'e':break
            print(str(recv_data,encoding='utf8'))
            #发消息
            send_data=recv_data
            conn.send(send_data)
        except Exception:
            break
    #挂电话
    conn.close()
单线程

   s.listen(n)    本身可以连接一个,n为挂起连接数

  服务端出现端口占用 ,修改端口号即可

  粘包问题:若发送大于1024  一次接收不完,被会出现此问题,下一次会打印未接受完的内容

    解决办法:先recv()一个长度,写循环接收

    具体解决办法如下:    

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import socket
import subprocess #导入执行命令模块
ip_port=('127.0.0.1',9999) #定义元祖
#买手机
s=socket.socket()  #绑定协议,生成套接字
s.bind(ip_port)    #绑定ip+协议+端口:用来唯一标识一个进程,ip_port必须是元组格式
s.listen(5)        #定义最大可以挂起胡链接数
#等待电话
while True:  #用来重复接收新的链接
    conn,addr=s.accept()   #接收客户端胡链接请求,返回conn(相当于一个特定胡链接),addr是客户端ip+port
    #收消息
    while True: #用来基于一个链接重复收发消息
            try: #捕捉客户端异常关闭(ctrl+c)
                recv_data=conn.recv(1024) #收消息,阻塞
                if len(recv_data) == 0:break #客户端如果退出,服务端将收到空消息,退出

                #发消息
                p=subprocess.Popen(str(recv_data,encoding='utf8'),shell=True,stdout=subprocess.PIPE) #执行系统命令,windows平
                                                                                                      # 台命令的标准输出是gbk编码,需要转换
                res=p.stdout.read()   #获取标准输出
                if len(res) == 0:   #执行错误命令,标准输出为空,
                    send_data='cmd err'
                else:
                    send_data=str(res,encoding='gbk')  #命令执行ok,字节gbk---->str---->字节utf-8

                send_data=bytes(send_data,encoding='utf8')


                #解决粘包问题
                ready_tag='Ready|%s' %len(send_data)
                conn.send(bytes(ready_tag,encoding='utf8')) #发送数据长度
                feedback=conn.recv(1024)  #接收确认信息
                feedback=str(feedback,encoding='utf8')

                if feedback.startswith('Start'):
                    conn.send(send_data)  #发送命令的执行结果
            except Exception:
                break
    #挂电话
    conn.close()
粘包问题_server
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:Alex Li
import socket
ip_port=('127.0.0.1',9999)
#买手机
s=socket.socket()
#拨号
s.connect(ip_port)  #链接服务端,如果服务已经存在一个好的连接,那么挂起

while True:        #基于connect建立的连接来循环发送消息
    send_data=input(">>: ").strip()
    if send_data == 'exit':break
    if len(send_data) == 0:continue
    s.send(bytes(send_data,encoding='utf8'))

    #解决粘包问题
    ready_tag=s.recv(1024) #收取带数据长度的字节:Ready|9998
    ready_tag=str(ready_tag,encoding='utf8')
    if ready_tag.startswith('Ready'):#Ready|9998
        msg_size=int(ready_tag.split('|')[-1])  #获取待接收数据长度
    start_tag='Start'
    s.send(bytes(start_tag,encoding='utf8')) #发送确认信息

    #基于已经收到的待接收数据长度,循环接收数据
    recv_size=0
    recv_msg=b''
    while recv_size < msg_size:
        recv_data=s.recv(1024)
        recv_msg+=recv_data
        recv_size+=len(recv_data)
        print('MSG SIZE %s RECE SIZE %s' %(msg_size,recv_size))

    print(str(recv_msg,encoding='utf8'))
    #挂电话
s.close()
粘包问题_client

 多线程

import socketserver

class MyServer(socketserver.BaseRequestHandler):
    def handle(self):
        # print self.request,self.client_address,self.server
          #conn
        self.request.sendall(bytes('欢迎致电 10086,请输入1xxx,0转人工服务.',encoding="utf-8"))
        while True:
            data = self.request.recv(1024)
            print("[%s] says:%s" % (self.client_address,data.decode() ))
            self.request.sendall(data.upper())

if __name__ == '__main__':
    server = socketserver.ThreadingTCPServer(('127.0.0.1',8009),MyServer)
    server.serve_forever()
server
import socket
ip_port=('127.0.0.1',8009)
#买手机
s=socket.socket()
#拨号
s.connect(ip_port)
#发送消息
welcome_msg = s.recv(1024)
print("from server:",welcome_msg.decode())
while True:
    send_data=input(">>: ").strip()
    if len(send_data) == 0:continue
    s.send(bytes(send_data,encoding='utf8'))

    #收消息
    recv_data=s.recv(1024)
    print(str(recv_data,encoding='utf8'))
    #挂电话
s.close()
clients

   多线程ssh:

import socketserver
import subprocess
class MyServer(socketserver.BaseRequestHandler):
    def handle(self):
        # print self.request,self.client_address,self.server
        self.request.sendall(bytes('欢迎致电 10086,请输入1xxx,0转人工服务.',encoding="utf-8"))
        while True:
            data = self.request.recv(1024)
            if len(data) == 0:break
            print("[%s] says:%s" % (self.client_address,data.decode() ))
            #self.request.sendall(data.upper())
            cmd = subprocess.Popen(data.decode(),shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
            cmd_res =cmd.stdout.read()
            if not cmd_res:
               cmd_res = cmd.stderr.read()
            if len(cmd_res) == 0: #cmd has not output 
               cmd_res = bytes("cmd has output",encoding="utf-8")
            self.request.send(cmd_res )


if __name__ == '__main__':
    server = socketserver.ThreadingTCPServer(('0.0.0.0',8009),MyServer)
    server.serve_forever()
多线程ssh_server

 

posted @ 2016-07-03 13:20  6随6心6  阅读(201)  评论(0编辑  收藏  举报