一、HTTP协议的socket通信

1、server.py

# 服务端
import sys
import socket ip_point = ('127.0.0.1',9999)
sk = socket.socket()
sk.bind(ip_point)
sk.listen(5)
print("进入监听状态...")
conn,addr = sk.accept()
print(addr)
client_data = conn.recv(1024)
print(client_data.decode("utf-8"))
conn.send("服务端回复内容:我很好。".encode("utf-8"))
conn.close()

2、client.py

# 客户端
import socket
ip_port = ("127.0.0.1",9999)
sk = socket.socket()
sk.connect(ip_port)
sk.send("客户端发送数据:你好吗?".encode("utf-8"))
server_replay = sk.recv(1024)
print("get data:",server_replay.decode("utf-8"))
sk.close()

3、执行结果

4、流程说明

  1. 建立socket对象
  2. socket绑定ip和端口
  3. listen
  4. 有连接,accept
  5. 读写数据
  6. 关闭

二、UDP协议的socket通信

1、server.py

# 服务端
from socket import *
from time import ctime HOST = ''
PORT = 1200
BUFSIZ = 128
ADDR = (HOST, PORT) # 创建一个服务器端UDP套接字
udpServer = socket(AF_INET, SOCK_DGRAM)
# 绑定服务器套接字
udpServer.bind(ADDR)
print('已经进入监听状态...')
# 接收来自客户端的数据
data, addr = udpServer.recvfrom(BUFSIZ)
print(u"得到客户端数据:",data.decode("utf-8"))
# 向客户端发送数据
udpServer.sendto(b'%s %s[%s]' % ("服务器发送消息:".encode("utf-8"),ctime().encode("utf-8"),data),addr)
print('向客户端发送数据:', data)
udpServer.close()

2、client.py

# 客户端
#encoding=utf-8
from socket import * HOST = 'localhost'
PORT = 1200
BUFSIZ = 128
ADDR = (HOST, PORT) # 创建客户端UDP套接字
udpClient = socket(AF_INET, SOCK_DGRAM)
data = input('>')
# 向服务器端发送数据
udpClient.sendto(data.encode("utf-8"), ADDR)
# 接收来自服务器端的数据
data, ADDR = udpClient.recvfrom(BUFSIZ)
print(data.decode("utf-8"))
udpClient.close()

3、结果

三、实现一个调用系统命令的例子

1、server.py

import os
if __name__ == '__main__':
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('localhost', 8001))
sock.listen(5)
while True:
connection,address = sock.accept()
try:
connection.settimeout(5)
command = connection.recv(1024)
print(command)
result=os.popen(command.decode("utf-8")) #拿到执行后管道命令后的结果
connection.send(command)
connection.send(result.read().encode("utf-8"))
except socket.timeout:
print('time out')
connection.close()

2、client.py

if __name__ == '__main__':
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('localhost', 8001))
import time
time.sleep(2)
sock.send('ipconfig'.encode("utf-8"))
print("command:",sock.recv(10).decode("utf-8"))
print ("command result:",sock.recv(1024).decode("utf-8"))
sock.close()

3、执行结果

客户端向服务端发送一个dos命令
服务服务端返回命令响应结果

四、实现聊天室

1、实现的效果:

2、服务器端代码

# encoding=utf-8
from twisted.internet.protocol import Factory
from twisted.protocols.basic import LineReceiver # 事件处理器
from twisted.internet import reactor class Chat(LineReceiver):#本质就是一个Protocol类的子类,真正管理server端和每个客户端通讯逻辑的,每一个客户端的连接,都会自动生成一个Chat类的实例。
message_dict={} #类变量,存储所有用户发送的消息,key:收消息的用户名,value:列表存所有发送来的消息
def __init__(self, users):
self.users = users #把ChatFactory类中的实例变量user字典,用self.users 变量引用这个字典
self.name = None #当前连接的用户名,你起的名字会存到这个变量里面
self.state = "GETNAME" #状态位,确认当前连接的客户端起名名字没有,没起名状态是GETNAME,起了名状态是CHAT def connectionMade(self): # 连接开始,且开始做处理
if self.name is None: #判断客户端有没有名字
self.sendLine(u"你叫什么名字?".encode("utf-8")) #给客户端发送指定消息! def connectionLost(self, reason): #连接断开的时候做什么处理
print("断开时的用户名:",self.name)
if self.name in self.users:
del self.users[self.name] #user字典是一个全局变量,value存的是连接对象本身(chat的实例),已经断开不是连接状态了,删除掉。
try:
if self.name in Chat.message_dict: #把别人给你发的消息,从消息字典中删除掉
del Chat.message_dict[self.name]
except:
print("删除用户的聊天记录失败") def lineReceived(self, line): # 收到客户端发来的消息做什么处理,会自动调用
#客户端发送的消息,会自动传到line这个变量里面
if self.state == "GETNAME": # 根据状态开始选择不同得内容处理
print("line:",line)
self.handle_GETNAME(line.decode("utf-8")) #调用起名字的处理方法handle_GETNAME
else:
self.handle_CHAT(line.decode("utf-8")) #调用聊天的处理方法handle_CHAT def handle_GETNAME(self, name): #处理用户起名字的逻辑
if name in self.users:
self.sendLine(u"名字冲突了,请做另外起个用户名.\n".encode("utf-8") ) # 每个用户只能有一个聊天通信存在
return
self.sendLine(("欢迎, %s!\n" %name).encode("utf-8")) #给客户端发送一个消息,告诉你欢迎xxx
self.name = name #用户发来的名字,赋值给self.name变量,连接的客户端的名字
self.users[name] = self #把self,自己,放到users字典中(存所有用户的连接对象---Chat的实例--self)
self.state = "CHAT" #把用户从GETNAME状态改为CHAT状态 def handle_CHAT(self, message): # 处理用户聊天的逻辑
#客户端输入:zhangsan:你吃了吗?
if "getmessage" in message: #发的命令是getmessage,读别人给你发的消息,取消息的用户名:getmessage
username = message.split(":")[0]#取到需要取消息的用户名
print("*"*2,username,Chat.message_dict)
#判断取消息的用户名在不在消息字典中,或者是不是消息为空
if (username not in Chat.message_dict) or Chat.message_dict[username] == []:
self.users[username].sendLine("没有别人给你发送的数据".encode("utf-8"))
print(message,"---->","没有别人给你发送的数据","\n")
return
message_list=Chat.message_dict[username]#把消息的列表取出来
print(message_list)
if username in self.users:#把所有的链接对象遍历一遍
print(username,self.users[username])
#self.users[username]--》username对应的链接对象取出来,然后把列表以字符串的形式发给客户端
#客户端,需要用eval(列表的字符串)---》转换为一个列表
#用这个连接对象发给用户这个列表字符串
self.users[username].sendLine(("%s" % message_list).encode("utf-8"))
del Chat.message_dict[username]#删除刚才收走的消息
return elif ":" in message:
'''
          消息格式:
huqiqi:zhangsan:你吃了么?
'''
if message.count(":")!=2:
self.sendLine("您发送的消息格式不对,请输入send命令后,按照格式‘用户名:消息’来进行聊天信息发送。".encode("utf8"))
print("您发送的消息格式不对,请输入send命令后,按照格式‘用户名:消息’来进行聊天信息发送。")
return
from_username = message.split(":")[0]
to_username = message.split(":")[1]
chat_message = message.split(":")[2]
if to_username not in Chat.message_dict:#判断接受者是否在消息字典中,不在,声明一个空列表作为value
Chat.message_dict[to_username] = []
Chat.message_dict[to_username].append((from_username,chat_message))#向列表中追加这个消息:(发消息人名字,消息体)
print(message, "---->", "增加了用户%s发送的消息:%s" %(to_username,(from_username,chat_message)) , "\n")
return #查看哪些用户处于登录状态
elif message.strip() =="list": #查看哪些用户是处于登录状态
print("list response")
self.sendLine((str([username for username in self.users]) + "\n").encode("utf-8"))
print(message, "---->", (str([username for username in self.users]) + "\n"),"\n")
return
#如果没有识别用户命令,提示用户可以输入使用的命令
else: #非上面的消息,就返回命令提示语
send_message= ("""请指定用户名,输入send后,按照格式‘用户名:消息’来进行聊天信息发送。
\n或者输入list查看当前登录用户\n输入getmessage获取其他用户发给你的聊天信息\n""")
#print (type(send_message))
self.sendLine(send_message.encode("utf-8"))
print(message, "---->",send_message,"\n")
return class ChatFactory(Factory): #实现的工厂类,必须定义buildProtocol方法,必须返回一个Protocol子类的实例对象
def __init__(self):
self.users = {} #将所有与服务器端连接的对象存放到此字典中,所有的实例均可以使用此字典获取所有的连接对象,字典来存储所有的连接,key:和server连接的客户端名字(第一次连接的时候取的);value:连接对象也就是Chat的实例 def buildProtocol(self, addr):
return Chat(self.users) #每次一个新的客户端建立了连接,那么会自动生成Chat类的实例,这个实例负责管理服务端和客户端的所有通讯细节,会根据网络事件,触发不同内置的事件方法! if __name__ == '__main__':
reactor.listenTCP(1200, ChatFactory()) #监听端口,指定通信协议的工厂类实例
print ("开始进入监听状态...")
reactor.run() #开始监听

3、客户端代码

# socket client end
from socket import *
import time
s = socket(AF_INET, SOCK_STREAM)
remote_host = gethostname()print ('remote_host:', remote_host)
port = 1200
s.connect((remote_host, port)) # 发起连接
print (u"连接从", s.getsockname()) # 返回套接字自己的地址。通常是一个元组(ipaddr,port)
print (u"连接到", s.getpeername()) # 返回连接套接字的远程地址。返回值通常是元组(ipaddr,port) print (u'从服务器返回消息:')
print (s.recv(1200).decode("utf-8").strip()) while 1:
username = input("请输入你要使用的英文用户名:\n")
s.send(('%s\r\n' %username.strip()).encode("utf-8")) # 发送一行字符串(以\r\n 结束)到服务器端
print (u'从服务器返回消息:')
response = s.recv(1200).decode("utf-8").strip()
print (response)
if "冲突" not in response:
break print("*"*50)
print("""查看当前登录用户列表的命令:list
查看别人给你发送的消息命令要求:getmessage
给别人发送消息,请先输入send,然后按照如下格式发送聊天信息:
username:要发送的消息
断开连接请输入bye""")
print("*"*50) while 1:
send_message=input("请输入发送的信息:\n")
if send_message=="getmessage" :
#当前用户名:getmessage --->发给服务器
s.send(('%s:%s\r\n' %(username,send_message)).encode("utf-8"))
print (u'从服务器返回消息:')
content = s.recv(1200).decode("utf-8").strip()
#返回的消息内容是个列表[(发消息人名1,消息1),(发消息人名2,消息2),(发消息人名3,消息3)....]
try:
if "[" in content and ']' in content:
#服务器返回的是个字符串,用eval转换为列表对象
info_list = eval(content)
for index,info in enumerate(info_list):#遍历
#index是序号,info[0]发消息的人名,info[1]是发送的消息体
print("%s>用户%s信息:%s" %(index,info[0],info[1]))
else:
print(content)
except:
print("从服务器收到的数据是无效数据!数据为%s" %content)
elif send_message=="list":
s.send(('%s\r\n' %send_message).encode("utf-8"))
print (u'从服务器返回消息:')
print (s.recv(1200).decode("utf-8").strip())
elif send_message=="bye":
s.close()
break
elif send_message=="send":
print("请输入你要给用户发送的消息,消息格式:\n用户名:您要发的消息内容\n")
info = input(">")
s.send(('%s:%s\r\n' %(username,info.strip())).encode("utf-8"))#发给server端
print("发送的消息:",('%s:%s\r\n' %(username,info.strip()))) #打印发送的消息
else:
print("输入的消息无效:请使用getmessage、list、bye或者send之一")
time.sleep(1)
continue

Socket编程和实现聊天室的更多相关文章

  1. Java 多线程Socket编程通讯--实现聊天室代码

    1.创建服务器类 import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import ja ...

  2. 网络编程TCP协议-聊天室

    网络编程TCP协议-聊天室(客户端与服务端的交互); <span style="font-size:18px;">1.客户端发数据到服务端.</span> ...

  3. 示例:Socket应用之简易聊天室

    在实际应用中,Server总是在指定的端口上监听是否有Client请求,一旦监听到Client请求,Server就会启动一个线程来响应该请求,而Server本身在启动完线程之后马上又进入监听状态. 示 ...

  4. Express+Socket.IO 实现简易聊天室

    代码地址如下:http://www.demodashi.com/demo/12477.html 闲暇之余研究了一下 Socket.io,搭建了一个简易版的聊天室,如有不对之处还望指正,先上效果图: 首 ...

  5. C#编程 socket编程之unity聊天室

    上面我们创建了tcp的客户端和服务端,但是只能进行消息的一次收发.这次我们做一个unity的简易聊天室,使用了线程,可以使用多个客户端连接服务器,并且一个客户端给服务器发消息后,服务器会将消息群发给所 ...

  6. 使用socket.io打造公共聊天室

    最近的计算机网络课上老师开始讲socket,tcp相关的知识,当时脑袋里就蹦出一个想法,那就是打造一个聊天室.实现方式也挺多的,常见的可以用C++或者Java进行socket编程来构建这么一个聊天室. ...

  7. 使用Android网络编程实现简易聊天室

    在Java中我们可以利用socket编程实现聊天室,在Android中也一样,因为Android完全支持JDK本身的TCP.UDP网络通信API.我们可以使用ServerSocket.Socket来建 ...

  8. Java利用TCP编程实现简单聊天室

    前言: 本文是我在学习尚学堂JAVA300集第二季网络编程部分仿照视频内容实现而成 具体可以去尚学堂官网观看视频学习 一.实现思路 实现聊天室的最核心部分就是JAVA的TCP网络编程. TCP 传输控 ...

  9. 手动搭建I/O网络通信框架4:AIO编程模型,聊天室终极改造

    第一章:手动搭建I/O网络通信框架1:Socket和ServerSocket入门实战,实现单聊 第二章:手动搭建I/O网络通信框架2:BIO编程模型实现群聊 第三章:手动搭建I/O网络通信框架3:NI ...

  10. 网络编程-基于Websocket聊天室(IM)系统

    目录 一.HTML5 - Websocket协议 二.聊天室(IM)系统的设计 2.1.使用者眼中的聊天系统 2.2.开发者眼中的聊天系统 2.3.IM系统的特性 2.4.心跳机制:解决网络的不确定性 ...

随机推荐

  1. 【接口自动化测试】Eolink Apilkit 安装部署,支持 Windows、Mac、Linux 等系统

    Eolink Apikit 有三种客户端,可以依据自己的情况选择.三种客户端的数据是共用的,因此可以随时切换不同的客户端. 我们推荐使用新推出的 Apikit PC 客户端,PC 端拥有线上产品所有的 ...

  2. 【译】ASP.NET Core在 .NET Core 3.1 Preview 1中的更新

    .NET Core 3.1 Preview 1现在可用.此版本主要侧重于错误修复,但同时也包含一些新功能. 这是此版本的ASP.NET Core的新增功能: 对Razor components的部分类 ...

  3. mpi转以太网连接300PLC在气动系统中的应用

    mpi转以太网连接300PLC在气动系统中的应用 某企业装备有限公司 摘要 工业通讯迅速发展的今天,MPI转以太网通讯已经发展为成熟,稳定,高效通讯 方式,兴达易控自主研发的MPI转以太网模块MPI- ...

  4. Spring扩展接口(1):ApplicationContextInitializer

    在此系列文章中,我总结了Spring扩展接口,以及各个扩展点的使用场景.并整理出一个bean在spring中从被加载到初始化到销毁的所有可扩展点的顺序调用图.这样,我们也可以看到bean是如何一步步加 ...

  5. 8月Node服务的3场事故

    有句话叫每一起严重事故的背后,必然有 29 次轻微事故和 300 起未遂先兆以及 1000 起事故隐患. 而我最近更是碰到了 3 起比较严重的线上事故,都是大意惹的祸. 一.数据库锁死 第一起事故发生 ...

  6. 其它——DevOps简介

    文章目录 DevOps简介 DevOps的概念 历史变革 好处是什么? 为什么DevOps会兴起? 实现DevOps需要什么? DevOps的采用现状 DevOps简介 DevOps 是一个完整的面向 ...

  7. 素数是个什么东西 prime number

    /**  * *********************************************************************  * 只有1和它本身两个正因数的自然数,叫质数 ...

  8. 如何编写难以维护的 React 代码?耦合通用组件与业务逻辑

    在众多项目中,React代码的维护经常变得棘手.其中一个常见问题是:将业务逻辑直接嵌入通用组件中,导致通用组件与业务逻辑紧密耦合,使其失去"通用性".这种做法使通用组件过于依赖具体 ...

  9. 征集 meme

    当你每次兴致勃勃地和好友分享自己喜欢的歌但 Ta 不屑一顾 / 不喜欢时:

  10. .NET开源简单易用、内置集成化的控制台、支持持久性存储的任务调度框架 - Hangfire

    前言 定时任务调度应该是平时业务开发中比较常见的需求,比如说微信文章定时发布.定时更新某一个业务状态.定时删除一些冗余数据等等.今天给推荐一个.NET开源简单易用.内置集成化的控制台.支持持久性存储的 ...