阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

TCP编程

265次阅读
没有评论

共计 7845 个字符,预计需要花费 20 分钟才能阅读完成。

一、客户端与服务端通信流程

TCP 编程

二、客户端与服务端通信代码

服务端 (server.py)

import socket
# 1、创建 socket
# 参数 1:选择使用 ip 类型,AF_INET 代表 ipv4,AF_INET6 表示 ipv6
# 参数 2:选择协议,SOCK_STREAM 表示 TCP 协议
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2、绑定
# 参数是一个元组,元组的第一个元素为服务器本机 IP,第二个元素为端口号,建议使用 8000(8000 以下的好多都是被其他程序所占用)以上的端口,最大使用到 65535
server.bind(("10.0.128.226", 8000))
# 3、监听:设置最大连接数
server.listen(40)
# 4、
while 1:
print("等待客户端连接……")
# 两个返回值,第一个返回值为连接的客户端的唯一标识,第二个返回值为客户端的 ip 地址
clientSocket, clientAddr = server.accept()
print("连接成功……")
print(clientSocket)
print(clientAddr)
# 接收数据
data = clientSocket.recv(1024)
print("%s 说:%s"%(clientAddr[0], data.decode("utf-8")))
# 响应数据
clientSocket.send("You are right!".encode("utf-8"))

客户端 (client.py)

import socket
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 参数是一个元组,元组的第一个元素为服务器所在机器的 IP,第二个元素为端口号,为要连接的服务器开放的端口
client.connect(("10.0.128.226", 8000))
# 发送数据
client.send("zutuanxue_com is a good man".encode("utf-8"))
data = client.recv(1024)
print("服务器说:%s"%(data.decode("utf-8")))

三、基于 TCP 实现聊天软件

TCP 编程

  • 服务器

    main.py

    from server import Server
    from db import Db
    def main():
    Db()
    server = Server(4, "TCP", "192.168.1.31", 8081, 10)
    server.start()
    if __name__ == "__main__":
    main()

    server.py

    import socket
    from interaction_thread import InteractionThread
    def single(cls):
    instance = {}
    def inner(*args, **kwargs):
    if cls not in instance:
    instance[cls] = cls(*args, **kwargs)
    return instance[cls]
    return inner
    @single
    class Server(object):
    def __init__(self, ip4or6, protocol, ip, port, num):
    if ip4or6 == 4:
    self.ip4or6 = socket.AF_INET
    else:
    self.ip4or6 = socket.AF_INET6
    if protocol.upper() == "TCP":
    self.protocol = socket.SOCK_STREAM
    else:
    self.protocol = socket.SOCK_DGRAM
    self.socket = None
    self.ip = ip
    self.port = port
    self.num = num
    def start(self):
    self.socket = socket.socket(self.ip4or6, self.protocol)
    self.socket.bind((self.ip, self.port))
    self.socket.listen(self.num)
    while True:
    clientSocket, clientAddr = self.socket.accept()
    print("用户 %s 连接成功" % (clientAddr[0]))
    # 为每个用户开启一个线程,和用户进行交互
    InteractionThread(clientSocket, clientAddr).start()

    user.py

    class User(object):
    def __init__(self, account, passwd, name, clientSocket=None):
    self.account = account
    self.passwd = passwd
    self.name = name
    self.clientSocket = clientSocket
    self.friendsDict = {} # account:user
    self.friendsFlag = {} # account:1/0

    db.py

    def single(cls):
    instance = {}
    def inner(*args, **kwargs):
    if cls not in instance:
    instance[cls] = cls(*args, **kwargs)
    return instance[cls]
    return inner
    @single
    class Db(object):
    def __init__(self):
    self.users = {} # account:user

    interaction_thread.py

    import threading
    from db import Db
    from user import User
    class InteractionThread(threading.Thread):
    def __init__(self, clientSocket, clientAddr):
    super().__init__()
    self.clientSocket = clientSocket
    self.clientAddr = clientAddr
    self.myself = None
    def run(self):
    db = Db()
    while True:
    data = self.clientSocket.recv(1024).decode("utf-8")
    print("服务器收到 %s 的 %s 信息"%(self.clientAddr[0], data))
    dataArr = data.split("#")
    flag = dataArr[0]
    if flag == "register":
    if len(dataArr) != 4:
    self.clientSocket.send("注册时输入有误".encode("utf-8"))
    continue
    account = dataArr[1]
    user = db.users.get(account)
    if user:
    self.clientSocket.send("账号存在,注册失败".encode("utf-8"))
    else:
    user = User(account, dataArr[2], dataArr[3])
    db.users[account] = user
    self.clientSocket.send("注册成功".encode("utf-8"))
    elif flag == "login":
    if len(dataArr) != 3:
    self.clientSocket.send("登陆时输入有误".encode("utf-8"))
    continue
    account = dataArr[1]
    user = db.users.get(account)
    if user:
    if user.passwd == dataArr[2]:
    # 给账号的 clientSocket 属性赋值
    user.clientSocket = self.clientSocket
    self.clientSocket.send("登陆成功".encode("utf-8"))
    self.myself = user
    else:
    self.clientSocket.send("密码错误,登陆失败".encode("utf-8"))
    else:
    self.clientSocket.send("账号不存在,登陆失败".encode("utf-8"))
    elif flag == "talk":
    if len(dataArr) != 2:
    self.clientSocket.send("群聊时输入有误".encode("utf-8"))
    continue
    # 自己未登录
    if not self.myself:
    self.clientSocket.send("未登录,请登录后操作".encode("utf-8"))
    continue
    for account in db.users:
    user = db.users.get(account)
    if (not user.clientSocket) or account == self.myself.account:
    continue
    # xxx 说 (群聊):xxxxxxxxxx
    info = "%s[%s] 说 (群聊):%s" % (self.myself.name, self.myself.account, dataArr[1])
    user.clientSocket.send(info.encode("utf-8"))
    elif flag == "quite":
    if len(dataArr) != 2:
    self.clientSocket.send("退出时输入有误".encode("utf-8"))
    continue
    account = dataArr[1]
    if account == self.myself.account:
    db.users.get(account).clientSocket = None
    self.myself = None
    self.clientSocket.send("成功退出".encode("utf-8"))
    else:
    self.clientSocket.send("只能退出自己的账号,退出失败".encode("utf-8"))
    elif flag == "add":
    if len(dataArr) != 2:
    self.clientSocket.send("添加好友时输入有误".encode("utf-8"))
    continue
    account = dataArr[1]
    user = db.users.get(account)
    if user:
    friend = self.myself.friendsDict.get(account)
    if friend:
    self.clientSocket.send("该用户已是好友".encode("utf-8"))
    else:
    # 对方成为我的好友
    self.myself.friendsDict[account] = user
    self.myself.friendsFlag[account] = 1
    self.clientSocket.send("好友添加成功".encode("utf-8"))
    # 把我添加到对方的好友列表
    user.friendsDict[self.myself.account] = self.myself
    # 但是对方未验证
    user.friendsFlag[self.myself.account] = 0
    # 告诉对方
    info = "%s[%s] 添加你为好友" % (self.myself.name, self.myself.account)
    user.clientSocket.send(info.encode("utf-8"))
    else:
    self.clientSocket.send("账号不存在,添加好友失败".encode("utf-8"))
    elif flag == "check":
    if len(dataArr) != 3:
    self.clientSocket.send("验证好友时输入有误".encode("utf-8"))
    continue
    friendAccount = dataArr[1]
    friend = self.myself.friendsDict.get(friendAccount)
    flag = dataArr[2]
    if flag == "yes":
    self.myself.friendsFlag[friendAccount] = 1
    # 告诉对方
    info = "%s[%s] 已同意添加好友请求"%(self.myself.name, self.myself.account)
    friend.clientSocket.send(info.encode("utf-8"))
    elif flag == "no":
    friend.friendsDict.pop(self.myself.account)
    friend.friendsFlag.pop(self.myself.account)
    self.myself.friendsDict.pop(friendAccount)
    self.myself.friendsFlag.pop(friendAccount)
    info = "%s[%s] 已拒绝添加好友请求" % (self.myself.name, self.myself.account)
    friend.clientSocket.send(info.encode("utf-8"))
    elif flag == "say":
    if len(dataArr) != 3:
    self.clientSocket.send("私聊时输入有误".encode("utf-8"))
    continue
    account = dataArr[1]
    friend = db.users.get(account)
    # 验证对方是否添加你为好友
    if friend.friendsFlag[self.myself.account] == 1:
    info = "%s[%s] 说 (私聊):%s" % (self.myself.name, self.myself.account, dataArr[2])
    friend.clientSocket.send(info.encode("utf-8"))
    else:
    self.clientSocket.send("对方未添加你为好友".encode("utf-8"))
    elif flag == "del":
    if len(dataArr) != 2:
    self.clientSocket.send("删除好友时输入有误".encode("utf-8"))
    continue
    account = dataArr[1]
    friend = db.users.get(account)
    friend.friendsDict.pop(self.myself.account)
    friend.friendsFlag.pop(self.myself.account)
    self.myself.friendsDict.pop(account)
    self.myself.friendsFlag.pop(account)
    info = "%s[%s] 将你删除好友"%(self.myself.name, self.myself.account)
    friend.clientSocket.send(info.encode("utf-8"))
  • 客户端

    main.py

    from client import Client
    from send_thread import SendThread

from recv_thread import RecvThread

def main():
c = Client(4,“TCP”,“192.168.1.31”, 8081)
c.start()

# 启动发送线程
sth = SendThread(c)
sth.start()
# 启动接收线程
rth = RecvThread(c)
rth.start()
# 等待发送与接收线程的结束
sth.join()
rth.join()

if name ==“main”:
main()

client.py
```python
import socket
def single(cls):
instance = {}
def inner(*args, **kwargs):
if cls not in instance:
instance[cls] = cls(*args, **kwargs)
return instance[cls]
return inner
@single
class Client(object):
def __init__(self, ip4or6, protocol, ip, port):
if ip4or6 == 4:
self.ip4or6 = socket.AF_INET
else:
self.ip4or6 = socket.AF_INET6
if protocol.upper() == "TCP":
self.protocol = socket.SOCK_STREAM
else:
self.protocol = socket.SOCK_DGRAM
self.socket = None
self.ip = ip
self.port = port
def start(self):
self.socket = socket.socket(self.ip4or6, self.protocol)
self.socket.connect((self.ip, self.port))

send_thread.py

import threading
class SendThread(threading.Thread):
def __init__(self, client):
super().__init__()
self.client = client
def run(self):
while True:
# 注册 register#account#passwd#name
# 登陆 login#account#passwd
# 群聊 talk#data
# 退出登录 quite#account
# 添加好友 add#account
# 验证好友添加 check#account#yes/no
# 与好友私聊 say#account#data
# 删除好友 del#account
# register#a#1#zutuanxue_com
# register#b#2#kaige
# register#c#3#kaishen
# talk#zutuanxue_com is a good man
# login#a#1
# login#b#2
# login#c#3
# quite#c
# add#b check#a#yes
# add#c check#b#no
# say#b#zutuanxue_com is a good man
# say#a#zutuanxue_com is a good man
# say#c#zutuanxue_com is a good man
# del#b
data = input()
self.client.socket.send(data.encode("utf-8"))

recv_thread.py

import threading
class RecvThread(threading.Thread):
def __init__(self, client):
super().__init__()
self.client = client
def run(self):
while True:
print(self.client.socket.recv(1024).decode("utf-8"))

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-05-26发表,共计7845字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中