Python笔记17.11.3

网络编程

网络:
 要解决哪些问题? 首先需要通信协议:
 tcp udp http ftp pop3 smtp
 tcp:可靠,有状态,长连接的协议
 主叫方  被叫方
     服务套接字 =>接受客户套接字的请求
  客户套接字 == 客户套接字
 udp:不可靠,无连接

Socket

Socket又称”套接字”,应用程序通常通过”套接字”向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。
Python 提供了两个级别访问的网络服务:
低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口的全部方法。
高级别的网络服务模块 SocketServer, 它提供了服务器中心类,可以简化网络服务器的开发。

使用Socket实现一对一聊天(TCP)
服务端

import socket
import threading
ss = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ss.bind(("localhost",9999))
ss.listen(5)
print('开始等待客户的请求')
c = ss.accept()
print('某个客户连接到我了')
def myrecv(c):
    while True:
        msg=c[0].recv(1024)
        print(msg.decode())
threading._start_new_thread(myrecv,(c,))
while True:
    msg = input()
    c[0].send(msg.encode())

除了socket模块以外,还使用了threading用一个新线程来做消息接受。

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

首先我们使用 socket 模块的 socket 函数来创建一个 socket 对象。socket 对象可以通过调用其他函数来设置一个 socket 服务。

ss.bind(("localhost",9999))
ss.listen(5)

然后用bind()方法来绑定ip和端口号(参数类型为元组),再用listen()来设置最大连接数,超过最大连接数后排队。

c = ss.accept()

accept()方法来等待客户端请求,这个方法回返回一个元组,里面包含了一个套接字对象和客户端的地址。

def myrecv(c):
    while True:
        msg=c[0].recv(1024)
        print(msg.decode())
threading._start_new_thread(myrecv,(c,))
while True:
    msg = input()
    c[0].send(msg.encode())

方法myrecv(c)是用来循环接收数据并打印,我们用一个线程来接管他。用c[0]也就是之前接收到的套接字对象来调用recv(指定最大数据量)方法接收数据,这个方法是返回的字符串类型,我们要打印需要用decode()方法来解码不然会乱码。
底下的循环是接收控制台输入的字符串并用send()方法发送,需要先用encode()方法进行编码。

客户端

import socket
import threading

c = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
c.connect(('localhost',9999))   #连接对方,不成功抛出异常
def myrecv(c):
    while True:
        msg=c.recv(1024)
        print(msg.decode())
threading._start_new_thread(myrecv,(c,))

while True:
    msg = input()
    c.send(msg.encode())

比服务端相对简单,同样先创建一个socket对象,只不过我们只需要使用connect()方法连接到我们开启的服务器上就可以了。

多人同时聊天
实现理念:改造服务端,两个线程一个线程接受数据,一个线程把收到的数据发送出去
服务端

import socket
import threading
ss = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ss.bind(('0.0.0.0',9999))
ss.listen(10)
msg=None
lock = threading.Lock()
cond = threading.Condition(lock)
def server_recv(c,a):
    global msg
    while True:
        str1=c.recv(1024)
        cond.acquire()
        msg=str1
        msg=str(a)+str1.decode()
        cond.notify_all()
        cond.release()

def server_send(c,a):
    global msg
    while True:
        cond.acquire()
        cond.wait()
        cond.release()
        c.send(msg.encode())


while True:
    c,a = ss.accept()
    threading._start_new_thread(server_recv,(c,a))
    threading._start_new_thread(server_send,(c,a))

与之前不同

msg=None
lock = threading.Lock()
cond = threading.Condition(lock)

msg是用来储存信息的变量,因为暂时只缓存一条数据,所以为了保证线程安全,每条信息都被发送出去,我们需要一个线程锁来控制msg这个变量让它在被发送出去之前不会被改写。

def server_recv(c,a):
    global msg
    while True:
        str1=c.recv(1024)
        cond.acquire()
        msg=str1
        msg=str(a)+str1.decode()
        cond.notify_all()
        cond.release()

接受方法,比之前多了一个参数a,是在accept的时候接受到的地址,以便辨识身份。在方法内调用全局变量msg,首先用str1一个临时变量保证接受到数据,然后线程上锁,把msg赋值后唤醒发送方法,等待发送完成之后再进行接受数据。

def server_send(c,a):
    global msg
    while True:
        cond.acquire()
        cond.wait()
        cond.release()
        c.send(msg.encode())

接受方法,首先线程上锁之后使用wait()方法等待接受消息的线程来唤醒本线程,在把信息发送出去后继续锁定线程等待唤醒。

连接数据库

import pymysql
db = pymysql.connect('localhost','root','root','ssh')
cursor = db.cursor()
# # 使用 execute()  方法执行 SQL 查询
# cursor.execute("SELECT VERSION()")
# # 使用 fetchone() 方法获取单条数据.
# data = cursor.fetchone()
# print ("Database version : %s " % data)

sql = '''
insert into stu(id,name) values(1,'zs')
'''
try:
    # 执行sql语句
    cursor.execute(sql)
    # 提交到数据库执行
    db.commit()
except:
    # 如果发生错误则回滚
    db.rollback()

# 关闭数据库连接
print('success')
db.close()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值