组团学

TCP编程

阅读 (200745)

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

截屏2020011413.39.07.png

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

服务端(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实现聊天软件

截屏2020011414.25.16.png

  • 服务器

    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"))
需要 登录 才可以提问哦