使用python基于socket的tcp服务器聊天室

# coding=utf-8
import socket,threading,time
'''代码说明:
    1.创建一个字典用于接受客户端的用户名和信息
    2.创建一个类对象client用于编写客户端套接字对象发送(sendMsg)、接收数据(recv)
    获取用户名(getID)、关闭服务器(close)和获取时间(getTime)方法
    3.创建函数new_client用于接收客户端的用户名和数据进行打印
    创建broadcast方法进行服务器数据的发送
    4.创建start_server用于开启服务器,将new_client定义为线程进行数据收发
    



'''
# 创建客户端存储对象
clients={}
class client(object):
    def __init__(self,socket,addr,username):
        # 创建连接地址对象
        self.addr=addr[0]
        self.port=addr[1]
        # 创建用户名对象
        self.username=username
        # 创建套接字对象
        self.socket=socket
    '''用于发送数据'''
    def sendMsg(self,msg,username,admin):
        try:
            if admin:
                # 以管理员身份发送数据
                self.socket.send("%s %s(管理员):%s"%(self.getTime(),username,msg).encode("utf-8"))
            else:
                self.socket.send("%s %s:%s"%(self.getTime(),username,msg).encode("utf-8"))
                return True
        except:
            return False
    '''用于接收套接字对象的数据'''
    def recv(self,mtu=1024):
        try:
            # 接收套接字对象的数据
            data=self.socket.recv(mtu)
            if data=='!q' or data is None:
                return False
            return data
        except:
            return False
    '''用于关闭套接字对象'''
    def close(self):
        try:
            # 关闭套接字对象
            self.socket.close()
            return True
        except:
            return False
    '''用于获取用户名'''
    def getID(self):
        return "%s-%s" %(self.addr,self.port)
    '''用于获取当前时间'''
    def getTime(self):
        # 以年月日时分秒的形式返回当前时间
        return str(time.strftime("%Y-%m-%d %H:%M:%S"))
'''用于创建套接字对象并获取用户名和数据'''
def new_client(c):
    try:
        # 开始连接
        print("%s(%s)尝试连接" %(c.addr,c.port))
        data=c.recv()
        # 设置用户名不为空
        if data is None:
            print("用户名不能为空")
            return False
        # 规定用户名长度
        if len(data)>16:
            print("用户名太长")
            return False
        # 将数据传回username
        c.username=data
        print("用户%s %s(%s)已连接" %(c.username,c.addr,c.port))
        # 将连接成功的数据传回服务端
        c.socket.send("已连接:".encode("utf-8"))
        while True:
            # 接收客户端发送的数据
            data=c.recv()
            if data is None:
                break
            else:
                print("用户%s %s(%s)发送了:%s" %(c.username,c.addr,c.port,data))
                broadcast(data,c.username)
    # 打印关于socket的错误
    except socket.error as e:
        print("套接字错误:%s" % str(e))
    # 打印其他错误
    except Exception as e:
        print("其他错误:%s" %str(e))
    # 关闭服务端
    finally:
        print("%s(%s) 断开连接" %(c.addr,c.port))
        c.close()
        # 根据用户名删除客户端的信息
        global client
        clients.pop(c.getID())
# 用于发送客户端的所有信息
def broadcast(msg,username,admin=False):
    for c in clients.values():
        c.sendMsg(msg,username,admin)
'''用于创建并开启套接字对象'''
def start_server(port):
    server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    # 设置服务端套接字对象可复用IP地址
    server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    # 设置本机IP
    host="192.168.189.1"
    # 给服务端绑定固定的IP地址和端口
    server.bind((host,port))
    # 监听客户端,最多十个客户同时连入
    server.listen(10)
    print(f"服务器开启,正在监听{server.getsockname()}")
    while True:
        # 接收客户端收到的信息
        conn,addr=server.accept()
        c=client(conn,addr,"")
        # 将输入的用户名传给客户端套接字
        clients[c.getID()]=c
        t=threading.Thread(target=new_client,args=(c,)).start()
'''主函数'''
if __name__ == '__main__':
    start_server(7879)

TCP服务端

# coding=utf-8
import socket
import time
from socket import *
from threading import Thread
from time import sleep
import sys
'''代码说明:再main函数中创建一个空IP地址,开始扫描服务器,当连接到服务器时自动分配同网段的IP,若同意连接则将IP传入空IP
   若不连接则退出程序,创建两个线程分别用于接收服务端数据和发送数据给服务端,开启一个线程用于接收数据,当接收到数据时开启
   发送数据线程,当输入!q或者不输入数据时结束程序,实现客户端的收发
'''
# 设置开启客户端的标志位
running=False
'''设置发送数据的方法'''
def send(client):
    # 每次发送数据都延迟0.5s
    time.sleep(0.5)
    while True:
        data=input("")
        client.send(data.encode("utf-8"))
        if data=='!q' or not data:
            running=False
            break
'''设置接收数据的方法'''
def recv(client,t2):
    # 每次连接成功后先输入用户名
    username=input("输入用户名")
    # 发送用户名到服务端
    client.send(username.encode("utf-8"))
    # 开启发送数据的进程
    t2.start()
    while running:
        try:
            data=client.recv(1024).decode("utf-8")
            if not data:
                break
            print(data)
        except:
            break

'''主函数'''
if __name__ == '__main__':
    # 创建主机IP
    ip=""
    # 获取客户端套接字的IP地址(gethostname是获取主机名)
    addrs=getaddrinfo(gethostname(),None)
    # print(gethostname())
    # 设置连接服务端被分配到的IP地址
    print("开始扫描服务器")
    # 分配主机号为100~254
    for i in range(100, 254):
        client=socket(AF_INET,SOCK_STREAM)
        # 设置套接字对象地址可复用
        client.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
        # 设置套接字对象超时时间
        client.settimeout(1)
        temp="192.168.189.%s" %i
        try:
            # 连接服务端,若成功则返回0
            data=client.connect_ex((temp,7788))
            if data==0:
                print("找到服务器")
                # 设置是否连接服务器
                p=input("是否连接:y/n")
                # 若连接则将分配到的IP传入客户端
                if p=='y':
                    ip=temp
                    break
                # 若不连接则跳到程序结束关闭套接字
                else:
                    continue
        except:
            print("error")
        # 关闭客户端套接字
        client.close()
        # 若未分配到IP地址则连接失败结束程序
        if ip=="":
            print("未连接成功服务器")
            sys.exit()
        # 开启客户端套接字
        client=socket(AF_INET,SOCK_STREAM)
        try:
            client.connect((ip,7788))
            running=True
            # 创建两个线程,t1用于发送数据,t1用于接收数据
            t2=Thread(target=send,args=(client,))
            t1=Thread(target=recv,args=(client,t2))
            t1.start()
            t1.join()
            t2.join()
        # 若有错误就调至finally
        except:
            pass
        finally:
            # 关闭客户端套接字
            print("连接关闭")
            client.close()

TCP客户端

刚学完套接字(socket),写了一个聊天室,用函数写了一个以后就研究了一下怎么用面向对象的方式写了一个,可能会有点问题,希望大佬指点一下

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用TCP SOCKET技术完成聊天室Python代码示例: 服务器端代码: ```python import socket import threading HOST = '127.0.0.1' PORT = 8888 server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.bind((HOST, PORT)) server_socket.listen(5) clients = [] def handle_client(client_socket, address): while True: try: message = client_socket.recv(1024) if message: broadcast(message, client_socket) else: remove(client_socket) except: remove(client_socket) def broadcast(message, client_socket): for client in clients: if client != client_socket: try: client.send(message) except: client.close() remove(client) def remove(client_socket): if client_socket in clients: clients.remove(client_socket) while True: client_socket, address = server_socket.accept() clients.append(client_socket) print(f'Connected by {address}') threading.Thread(target=handle_client, args=(client_socket, address)).start() ``` 客户端代码: ```python import socket import threading HOST = '127.0.0.1' PORT = 8888 client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client_socket.connect((HOST, PORT)) def receive(): while True: try: message = client_socket.recv(1024) print(message.decode('utf-8')) except: print('Error receiving message') client_socket.close() break def send(): while True: message = input() client_socket.send(message.encode('utf-8')) threading.Thread(target=receive).start() threading.Thread(target=send).start() ``` 这是一个简单的聊天室实现,可以让多个客户端连接到服务器,实现多人同时在线的聊天功能。当客户端发送消息时,服务器会将消息广播给所有客户端,实现多人同时在线的交流。需要注意的是,这个实现还有很多不足之处,需要根据具体需求进行改进。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值