python -- 网络编程(TCP编程)

python的入门TCP编程 一、创建TCP服务器 创建TCP服务器的流程: 使用socket创建一个套接字 使用bind绑定IP和端口 使用listen让套接字变成可以被动连接 使用accept等待客户端的连接 使用recv/send接收和发送数据 例子:我们实现一个服务器向浏览器发送“Hello World”。 创建一个server.py文件 import socket #导入socket模块 host = '127.0.0.1' #主机IP port = 8080 #端口 web 阅读详情

TCP编程

  • Socket编程,需要两端,一般来说需要一个服务端、一个客户端,服务端称为Server,客户端称为Client
  • 这种编程模式也称为 CS编程

TCP服务端编程

服务端编程步骤

  • 创建Socket对象

  • 绑定IP地址Address和端口Port。使用bind()方法
    IPv4地址为一个二元组('IP地址字符串‘, Port)

  • 开始监听,将再指定的IP端口上监听。使用listen()方法

  • 获取用于传送数据的socket对象
    socket.accrpt() -> (socket object, address info)
    accept方法阻塞等待客户端创立连接,返回一个新的Socket对象和客户端地址的二元组
    地址是远程客户端的地址,IPv4中它是一个二元组(clientaddr, port)
    接受数据

    • recv(bufsize[, flags]) 使用缓冲区接受数据

    发送数据

    • send(bytes) 发送数据,必须传入一个bytes

在这里插入图片描述

问题

两次绑定同一个监听端口会怎么样?

import socket

s = socket.socket() # 创建socket对象,TCP连接 IPv4
ip = '127.0.0.1' # 本机回环地址
port = 9999 # TCP 65536
s.bind((ip, port)) # 一个地址和端口二元组
s.listen() # 开始监听,等待客户端连接到来

# 接入一个到来的连接
s1, info = s.accept() # 阻塞直到和客户端成功建立连接,返回一个新的socket对象和客户端地址
print(s1, info)

# 使用缓冲区获取诗句
data = s1.recv(1024) # 阻塞
print(info, data)
s1.send(b'hello world')
s1.close()

# 接入另一个连接
s2, info = s.accept()
data = s2.recv(1024)
print(info, data)
s2.send(b'hello python')
s2.close()

s.close()

上例accept和recv是阻塞的,主线程经常被阻塞住而不能工作

客户端操作

使用测试工具模拟客户端进行测试
在这里插入图片描述

  • 灰色,需点连接才可成功连接
    在这里插入图片描述
查看监听端口
  • windoes 命令
    netstat -anp tcp | findstr 9999
  • linux 命令
    netstat -tanl | grep 9999
    或
    ss -tanl | grep 9999
    ss命令没有可使用pip install ss自行安装

注意

  • IP 127.0.0.1 指本机回环地址,永远指向本机
  • port 端口 linux 用1000以上,这是一个两字节数,范围[0,65535] ,共65536种状态,当前此协议的此端口不能被别人占用
  • server.bild() 绑定一个二元组,不可多次绑定同一个端口
  • listen() 监听,不可多次监听,真正的显示出端口
  • 打开的资源必须关闭,会占用文件描述符 fd

实现服务端主动断开连接 收发各一次

# TCP Server 端开发
import socket

server = socket.socket() # TCP 连接 IPv4
ip = '127.0.0.1'
port = 9999 # TCP 65536
server.bind((ip, port)) # address

server.listen() # 真正的显示出端口
print(server)

newsock, clientinfo = server.accept() # 默认阻塞


data = newsock.recv(1024) # 阻塞,buffer空
print(data)
newsock.send('server acl. data={}'.format(data).encode()) # buffer 满
newsock.close()

server.close()

执行结果

  • 服务端控制台结果
<socket.socket fd=508, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999)>
b'hello world'

Process finished with exit code 0
  • 客户端结果
    在这里插入图片描述

服务端循环接受客户端信息

# TCP Server 端开发
import socket

server = socket.socket() # TCP 连接 IPv4
ip = '127.0.0.1'
port = 9999 # TCP 65536
server.bind((ip, port)) # address

server.listen() # 真正的显示出端口
print(server)

newsock, clientinfo = server.accept() # 默认阻塞
print(newsock)
print('new1', clientinfo)
while True:
    data = newsock.recv(1024) # 阻塞,buffer空
    print(data)
    newsock.send('server acl. data={}'.format(data).encode()) # buffer 满
newsock.close()

server.close()

执行结果

  • 服务端控制台结果
<socket.socket fd=552, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999)>
<socket.socket fd=556, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 9999), raddr=('127.0.0.1', 54481)>
new1 ('127.0.0.1', 54481)
b'hello world'
b'hello python'
b''
Traceback (most recent call last):
  File "C:/Users/mayn/PycharmProjects/mypython/m/t1.py", line 16, in <module>
    data = newsock.recv(1024) # 阻塞,buffer空
ConnectionAbortedError: [WinError 10053] 你的主机中的软件中止了一个已建立的连接。

Process finished with exit code 1
  • 客户端结果
    在这里插入图片描述

因上例代码中未设置循环退出条件,故手动中断连接会抛异常

实战 – 写一个群聊程序

需求分析

聊天工具是CS程序,C是每一个客户端client,S是服务器端server。
服务器应该具有的功能:

  1. 启动服务,包括绑定地址和端口,并监听
  2. 建立连接,能和多个客户端建立连接
  3. 接收不同用户的信息
  4. 分发,将接收的某个用户的信息转发到已连接的所有客户端
  5. 停止服务
  6. 记录连接的客户端
代码实现
  • 服务端应该对应一个类
class ChatServer:
    def __init__(self, ip, port): # 启动服务
        self.sock = socket.socket()
        self.addr = (ip, port)

    def start(self): # 启动监听
        pass

    def accept(self): # 多人连接
        pass

    def recv(self): # 接受客户端数据
        pass

    def stop(self): # 停止服务
        pass
  • 在此基础上,扩展完成
import logging
import socket
import threading
import datetime

logging.basicConfig(level=logging.INFO, format="%(asctime)s %(thread)d %(message)s")


class ChatServer:
    def __init__(self, ip='127.0.0.1', port=9999): # 启动服务
        self.sock = socket.socket()
        self.addr = (ip, port)
        self.clients = {} # 客户端

    def start(self): # 启动监听
        self.sock.bind(self.addr) # 绑定
        self.sock.listen() # 监听
        # accept会阻塞主线程,所以开一个新的线程
        threading.Thread(target=self.accept).start()

    def accept(self): # 多人连接
        while True:
            sock, client = self.sock.accept() # 阻塞
            self.clients[client] = sock # 添加到客户端字典
            # 准备接受数据,recv是阻塞的,开启新的线程
            threading.Thread(target=self.recv, args=(sock, client)).start()

    def recv(self, sock:socket.socket, client): # 接受客户端数据
        while True:
            data = sock.recv(1024) # 阻塞到数据到来
            msg = "{:%Y/%m/%d %H:%M:%S} {}:{}\n{}\n".format(
                datetime.datetime.now(), *client, data.decode())
            logging.info(msg)
            msg = msg.encode()
            for s in self.clients.values():
                s.send(msg)
                
    def stop(self): # 停止服务
        for s in self.clients.values():
            s.close()
        self.sock.close()

cs = ChatServer()
cs.start()
  • 基本功能完成,但是有问题。使用Event改进
import logging
import socket
import threading
import datetime

logging.basicConfig(level=logging.INFO, format="%(asctime)s %(thread)d %(message)s")


class ChatServer:
    def __init__(self, ip='127.0.0.1', port=9999): # 启动服务
        self.sock = socket.socket()
        self.addr = (ip, port)
        self.clients = {} # 客户端
        self.event = threading.Event()

    def start(self): # 启动监听
        self.sock.bind(self.addr) # 绑定
        self.sock.listen() # 监听
        # accept会阻塞主线程,所以开一个新的线程
        threading.Thread(target=self.accept).start()

    def accept(self): # 多人连接
        while not self.event.is_set():
            sock, client = self.sock.accept() # 阻塞
            self.clients[client] = sock # 添加到客户端字典
            # 准备接受数据,recv是阻塞的,开启新的线程
            threading.Thread(target=self.recv, args=(sock, client)).start()

    def recv(self, sock:socket.socket, client): # 接受客户端数据
        while not self.event.is_set():
            data = sock.recv(1024) # 阻塞到数据到来
            msg = "{:%Y/%m/%d %H:%M:%S} {}:{}\n{}\n".format(
                datetime.datetime.now(), *client, data.decode())
            logging.info(msg)
            msg = msg.encode()
            for s in self.clients.values():
                s.send(msg)

    def stop(self): # 停止服务
        self.event.set()
        for s in self.clients.values():
            s.close()
        self.sock.close()

cs = ChatServer()
cs.start()

while True:
    cmd = input('>>').strip()
    if cmd =='quit':
        cs.stop()
        threading.Event().wait(3)
        break        

这一版基本能用了,测试通过。但是还有要完善的地方
例如各种异常的判断,客户端断开连接后字典中的移除客户端数据等

  • 客户端主动断开带来的问题

    • 服务端知道自己何时断开,如果客户端断开,服务器不知道。(客户端主动断开,服务端recv会得到一个空串)
    • 所以,好的做法是,客户端断开发出特殊消息通知服务器端断开连接。但是,如果客户端主动断开,服务端主动发送一个空消息,超时返回异常,捕获异常并清理连接
    • 即使为客户端提供了断开命令,也不能保证客户端会使用它断开连接。但是还是要增加这个退出功能
  • 增加客户端退出命令

import logging
import socket
import threading
import datetime

logging.basicConfig(level=logging.INFO, format="%(asctime)s %(thread)d %(message)s")


class ChatServer:
    def __init__(self, ip='127.0.0.1', port=9999): # 启动服务
        self.sock = socket.socket()
        self.addr = (ip, port)
        self.clients = {} # 客户端
        self.event = threading.Event()

    def start(self): # 启动监听
        self.sock.bind(self.addr) # 绑定
        self.sock.listen() # 监听
        # accept会阻塞主线程,所以开一个新的线程
        threading.Thread(target=self.accept).start()

    def accept(self): # 多人连接
        while not self.event.is_set():
            sock, client = self.sock.accept() # 阻塞
            self.clients[client] = sock # 添加到客户端字典
            # 准备接受数据,recv是阻塞的,开启新的线程
            threading.Thread(target=self.recv, args=(sock, client)).start()

    def recv(self, sock:socket.socket, client): # 接受客户端数据
        while not self.event.is_set():
            data = sock.recv(1024) # 阻塞到数据到来
            msg = data.decode().strip()
            # 客户端退出命令
            if msg == 'quit' or msg == '': # 主动断开得到空串
                self.clients.pop(client)
                sock.close()
                logging.info('{} quits'.format(client))
                break

            msg = "{:%Y/%m/%d %H:%M:%S} {}:{}\n{}\n".format(
                datetime.datetime.now(), *client, data.decode())
            logging.info(msg)
            msg = msg.encode()
            for s in self.clients.values():
                s.send(msg)

    def stop(self): # 停止服务
        self.event.set()
        for s in self.clients.values():
            s.close()
        self.sock.close()

cs = ChatServer()
cs.start()

while True:
    cmd = input('>>').strip()
    if cmd =='quit':
        cs.stop()
        threading.Event().wait(3)
        break
    logging.info(threading.enumerate()) # 用来观察断开后线程的变化

程序还是有瑕疵,但是业务基本功能完成了
注意:

  • 由于GIL和内置数据结构的读写原子性,单独操作字典的某一项item是安全的。但是遍历过程是线程不安全的,遍历中有可能被打断,其他线程如果对字典元素进行增加、弹出,都会影响字典的size,就会抛出异常。所以还是要加锁Lock
  • 加锁后代码如下
import logging
import socket
import threading
import datetime

logging.basicConfig(level=logging.INFO, format="%(asctime)s %(thread)d %(message)s")


class ChatServer:
    def __init__(self, ip='127.0.0.1', port=9999): # 启动服务
        self.sock = socket.socket()
        self.addr = (ip, port)
        self.clients = {} # 客户端
        self.event = threading.Event()
        self.lock = threading.Lock()

    def start(self): # 启动监听
        self.sock.bind(self.addr) # 绑定
        self.sock.listen() # 监听
        # accept会阻塞主线程,所以开一个新的线程
        threading.Thread(target=self.accept).start()

    def accept(self): # 多人连接
        while not self.event.is_set():
            sock, client = self.sock.accept() # 阻塞
            with self.lock:
                self.clients[client] = sock # 添加到客户端字典
            # 准备接受数据,recv是阻塞的,开启新的线程
            threading.Thread(target=self.recv, args=(sock, client)).start()

    def recv(self, sock:socket.socket, client): # 接受客户端数据
        while not self.event.is_set():
            data = sock.recv(1024) # 阻塞到数据到来
            msg = data.decode().strip()
            # 客户端退出命令
            if msg == 'quit' or msg == '': # 主动断开得到空串
                with self.lock:
                    self.clients.pop(client)
                    sock.close()
                logging.info('{} quits'.format(client))
                break

            msg = "{:%Y/%m/%d %H:%M:%S} {}:{}\n{}\n".format(
                datetime.datetime.now(), *client, data.decode())
            logging.info(msg)
            msg = msg.encode()

            with self.lock:
                for s in self.clients.values():
                    s.send(msg)

    def stop(self): # 停止服务
        self.event.set()
        with self.lock:
            for s in self.clients.values():
                s.close()
        self.sock.close()

cs = ChatServer()
cs.start()

while True:
    cmd = input('>>').strip()
    if cmd =='quit':
        cs.stop()
        threading.Event().wait(3)
        break
    logging.info(threading.enumerate()) # 用来观察断开后线程的变化
    logging.info(cs.clients)

socket常用方法

名称含义
socket.recv(bufsize[, flags])获取数据。默认是阻塞的方式
socket.recvfrom(bufsize[, flags])获取数据,返回一个二元组(bytes, address)
socket.recv_into(buffer[, nbytes[, flags]])获取到nbytes的数据后,存储到buffer中。如果nbytes没有指定或0,将buffer大小的数据存入buffer中。返回接收的字节数
socket.recvfrom_into(buffer[, nbytes[, flags]])获取数据,返回一个二元组(bytes, address)到buffer中
socket.send(bytes[, flags])TCP发送数据
socket.sendall(bytes[, flags])TCP发送全部数据,成功返回None
socket.sendto(string[,flag],address)UDP发送数据
socket.sendfile(file, offset=0, count=None)发送一个文件直到EOF,使用高性能的os.sendfile机制,返回发送的字节数。如果win下不支持sendfile,或者不是普通文件,使用send()发送文件。offset告诉起始位置。3.5版本开始
名称含义
socket.getpeername()返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)
socket.getsockname()返回套接字自己的地址。通常是一个元组(ipaddr,port)
socket.setblocking(flag)如果flag为0,则将套接字设为非阻塞模式,否则将套接字设为阻塞模式(默认值)
非阻塞模式下,如果调用recv()没有发现任何数据,或send()调用无法立即发送数据,那么将引起socket.error异常
socket.settimeout(value)设置套接字操作的超时期,timeout是一个浮点数,单位是秒
值为None表示没有超时期。一般,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作(如connect()
socket.setsockopt(level,optname,value)设置套接字选项的值。比如缓冲区大小。太多了,去看文档
不同系统,不同版本都不尽相同

MakeFile

socket.makefile(mode='r', buffering=None, *, encoding=None, errors=None, newline=None)
创建一个与该套接字相关连的文件对象,将recv方法看做读方法,将send方法看做写方法

import socket

server = socket.socket()
server.bind(('127.0.0.1', 9999))
server.listen()

s, _ =server.accept()
f = s.makefile(mode='rw')

print(s.getpeername())
print(s.getsockname())

f = s.makefile('rw')
data = f.read(10) # 按行读取要使用readline方法
print(data)
f.write('return your msg: {}'.format(data))
f.flush()

f.close()
print(f.closed, s._closed)
s.close()
print(f.closed, s._closed)

server.close()
  • 服务端控制台执行结果
('127.0.0.1', 62161)
('127.0.0.1', 9999)
1234567890
True False
True True

Process finished with exit code 0
  • 客户端执行结果
    在这里插入图片描述
makefile练习
  • 使用makefile改写群聊类
import logging
import socket
import threading
import datetime

logging.basicConfig(level=logging.INFO, format="%(asctime)s %(thread)d %(message)s")

class ChatServer:
    def __init__(self, ip='127.0.0.1', port=9999): # 启动服务
        self.sock = socket.socket()
        self.addr = (ip, port)
        self.clients = {} # 客户端
        self.event = threading.Event()
        self.lock = threading.Lock()

    def start(self): # 启动监听
        self.sock.bind(self.addr) # 绑定
        self.sock.listen() # 监听
        # accept会阻塞主线程,开一个新线程
        threading.Thread(target=self.accept).start()

    def accept(self): # 多人连接
        while not self.event.is_set():
            sock, client = self.sock.accept() # 阻塞
            f = sock.makefile('rw') # 支持读写
            with self.lock:
                self.clients[client] = f, socket # 添加到客户端字典
            # 准备接受数据,recv是阻塞的,开启新的线程
            threading.Thread(target=self.recv, args=(f, client)).start()

    def recv(self, f, client): # 接受客户端数据
        while not self.event.is_set():
            data = f.readline() # 阻塞等一行来,即换行符
            msg = data.strip()
            print(msg, '~~~~~~~~~~~')
            # 客户端退出命令
            if msg == 'quit' or msg == '': # 主动断开得到空串
                with self.lock:
                    _, sock = self.clients.pop(client)
                    f.close()
                    sock.close()
                logging.info('{} quits'.format(client))
                break
            msg = "{:%Y/%m/%d %H:%M:%S {}:{}\n{}\n}".format(
                datetime.datetime.now(), *client, data)
            logging.info(msg)

            with self.lock:
                for ff,_ in self.clients.values():
                    ff.write(msg)
                    ff.flush()

    def stop(self): # 停止服务
        self.event.set()
        with self.lock:
            for f, s in self.clients.values():
                f.close()
                s.close()
        self.sock.close()

cs = ChatServer()
cs.start()

while True:
    cmd = input('>>').strip()
    if cmd == 'quit':
        cs.stop()
        threading.Event().wait(3)
        break
    logging.info(threading.enumerate()) # 用来观察断开后线程的变化
    logging.info(cs.clients)

上例完成了基本功能,但是,如果客户端主动断开,或者readline出现异常,就不会从clients中移除作废的socket。可以使用异常处理解决这个问题

ChatServer实验用完整代码

注意,这个代码为实验用,代码中瑕疵还有很多。Socket太底层了,实际开发中很少使用这么底层的接口。
增加一些异常处理。

import logging
import socket
import threading
import datetime

logging.basicConfig(level=logging.INFO, format="%(asctime)s %(thread)d %(message)s")

class ChatServer:
    def __init__(self, ip='127.0.0.1', port=9999): # 启动服务
        self.sock = socket.socket()
        self.addr = (ip, port)
        self.clients = {} # 客户端
        self.event = threading.Event()
        self.lock = threading.Lock()

    def start(self): # 启动监听
        self.sock.bind(self.addr) # 绑定
        self.sock.listen() # 监听
        # accept 会阻塞主线程,所以开一个新线程
        threading.Thread(target=self.accept).start()

    def accept(self): # 多人连接
        while not self.event.is_set():
            sock, client = self.sock.accept() # 阻塞
            f = sock.makefile('rw') # 支持读写
            with self.lock:
                self.clients[client] = f, sock # 添加到客户端字典
            # 准备接收收据, recv是阻塞的,开启新的线程
            threading.Thread(target=self.recv, args=(f, client)).start()

    def recv(self, f, client): # 接收客户端数据
        while not self.event.is_set():
            try: # 异常处理
                data = f.readline() # 阻塞等一行来,换行符
            except Exception as e:
                logging.error(e)
                data = 'quit'

            msg = data.strip()

            # 客户端命令退出
            if msg == 'quit' or msg == '': # 主动断开得到空船
                with self.lock:
                    _, sock = self.clients.pop(client)
                    f.close()
                    sock.close()
                logging.info('{} quits'.format(client))
                break
            msg = '{:%Y/%m/%d %H:%M:%S} {}:{}\n{}\n'.format(
                datetime.datetime.now(), *client, data)
            logging.info(msg)

            with self.lock:
                for ff,_ in self.clients.values():
                    ff.write(msg)
                    ff.flush()

    def stop(self): # 停止服务
        self.event.set()
        with self.lock:
            for f, s in self.clients.values():
                f.close()
                s.close()
        self.sock.close()

def main():
    cs = ChatServer()
    cs.start()

    while True:
        cmd = input('>>').strip()
        if cmd == 'quit':
            cs.stop()
            threading.Event().wait(3)
            break
        logging.info(threading.enumerate()) # 用来观察断开后线程的变化
        logging.info(cs.clients)

if __name__ == '__main__':
    main()

TCP客户端编程

客户端编程步骤
  • 创建Socket对象
  • 连接到远端服务端的ip和port,connect()方法
  • 传输数据
    使用send、recv方法发送、接收数据
  • 关闭连接,释放资源
import socket


client = socket.socket()
ipaddr = ('127.0.0.1', 9999)
client.connect(ipaddr) # 直接连接服务器

client.send(b'abcd\n')
data = client.recv(1024) # 阻塞等待
print(data)

client.close()
  • 开始编写客户端类
import socket
import threading
import datetime
import logging

FORMAT = "%(asctime)s %(threadName)s %(thread)d %(message)s"
logging.basicConfig(format=FORMAT, level=logging.INFO)

class ChatClient:
    def __init__(self, ip='127.0.0.1', port=9999):
        self.sock = socket.socket()
        self.addr = (ip, port)
        self.event = threading.Event()

    def start(self): #  启动对远端服务器的链接
        self.sock.connect(self.addr)
        self.send("I'm ready.")
        # 准备接收数据,recv是阻塞的,开启新的线程
        threading.Thread(target=self.recv, name="recv").start()

    def recv(self): # 接收客户端的数据
        while not self.event.is_set():
            try:
                data = self.sock.recv(1024) # 阻塞
            except Exception as e:
                logging.error(e)
                break
            msg = "{:%Y/%m/%d %H:%M:%S} {}:{}\n{}\n".format(
                datetime.datetime.now(), *self.addr, data.strip())
            logging.info(msg)

    def send(self, msg:str):
        data = "{}\n".format(msg.strip().encode()) # 服务器需要一个换行符
        self.sock.send(data)

    def stop(self):
        self.sock.close()
        self.event.wait(3)
        self.event.set()
        logging.info('Client stops.')

def main():
    cc = ChatClient()
    cc.start()
    while True:
        cmd = input('>>')
        if cmd.strip() == 'quit':
            cc.stop()
            break
        cc.send(cmd) # 发送消息

if __name__ == '__main__':
    main()

同样,这样的客户端还是有些问题的,仅用于测试

TCP (传输控制协议)和 UDP 传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。是为了在不可靠的互联网络上提供可靠的端到端字节流而专门设计的一个传输协议。 TCP是一种面向广域网的通信协议,目的是在跨越多个网络通信时,为两个通信端点之间提供一条具有下列特点的通信方式: (1)基于流的方式; (2)面向连接; (3)可靠通信方式; (4)在网络... 阅读详情

相关推荐

Python 网络编程 TCP/UDP 详细基础

1 基础概念 1.1 Linux Windows 命令行查看网络信息 Linux: ifconfig windows: ipconfig 开/关网卡:sudo ifconfig ###(网卡名) up/down 1.2 IP地址 IP地址(Internet Protocol Address)是指互联网协议地址,又译为网际协议地址。 IP地址是IP协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异。 IP地址即在网络中标识一台.

weixin_55643605的博客 4821

Python网络编程之TCP

TCP协议,传输控制协议(Transmission Control Protocol,TCP)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC793定义。TCP通信需要经过创建连接、数据传送、终止连接三个步骤。正在上传…重新上传取消TCP通信模型中,在通信开始之前,一定要先建立相关的链接,才能发送数据。

AI创世纪的博客 3880

Python网络编程实战:构建TCP服务器与客户端

首先,我们需要创建一个socket对象。本文将详细介绍如何在Python中进行网络编程,特别是如何使用socket模块创建一个简单的TCP服务器和客户端。最后,我们需要编写一个循环来接受客户端的连接请求,并处理接收到的数据。在这个例子中,我们首先创建了一个socket对象,并使用connect()方法连接到服务器。然后,我们使用sendall()方法发送一条消息给服务器,并使用recv()方法接收服务器的响应。在这个例子中,我们使用了’localhost’作为地址,这意味着服务器只接受来自本机的连接。

铭渊老黄 2139

python网络编程(Tcp/Ip网络通讯协议)

Python网络编程是指使用Python编程语言进行网络通信和网络应用开发的技术。Python提供了一系列的网络编程库和模块,可以方便地进行网络通信、创建网络服务器、编写网络应用等。Python的网络编程模块包括socket、select、asyncio等。其中,socket模块是Python最基础、最常用的网络编程模块,提供了对套接字编程的支持,可以创建TCP、UDP等类型的套接字,进行网络通信。select模块提供了对I/O多路复用的支持,可以同时监听多个套接字的I/O事件。

m0_65995252的博客 4726

【python】网络编程socket TCP UDP

互联网协议族 即通用标准协议,任何私有网络只要支持这个协议,就可以接入互联网。

weixin_38009144的博客 1518

Windows系统下AutoDock 4.2.6安装避坑指南(附MGLTools配置技巧)

本文详细介绍了在Windows系统下安装和配置AutoDock 4.2.6的完整流程,特别针对分子对接研究中常见的软件安装问题提供了解决方案。从环境准备、分步安装到常见报错处理,涵盖MGLTools配置技巧、工作目录设置和环境变量优化,帮助科研人员快速搭建稳定的分子对接平台。

weixin_29234239的博客 313

【Python】网络编程之UDP、TCP

Socket的英文原义是“孔”或“插座”,网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。建立网络通信连接至少要一对端口号(socket),socket本质是编程接口(API),对TCP/IP的封装,TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口。基本上,Socket 是任何一种计算机网络通讯中最基础的内容。

专注上位机开发、机器视觉、机器学习、嵌入式软硬件开发 1万+

Blender关于GIS安装及使用天地图

Blender下载安装及GIS插件的安装及使用

Miss_SQ的博客 6969

Python网络编程之TCP协议(二)

网络编程是现代软件开发中不可或缺的一部分。无论是构建Web应用程序、移动应用后端,还是进行分布式系统开发、物联网设备通信,都离不开网络编程技术。在众多网络协议中,TCP(Transmission Control Protocol,传输控制协议)以其可靠性、面向连接的特性,成为应用最广泛的协议之一。Python作为一门功能强大且易于学习的编程语言,提供了丰富的网络编程库,使得开发者能够轻松地构建基于TCP协议的网络应用。

专注Rust编程与技术分享,涵盖C++、Python等开发实战,新手友好,专注实战,助力编程成长。 13万+

Win10系统下Protel 99 SE元件库导入报错?3步搞定File is not recognized问题

本文详细介绍了在Win10系统下解决Protel 99 SE元件库导入报错'File is not recognized'的3步终极方案。通过手动修改配置文件、使用专用工具和优化系统兼容性设置,帮助用户快速解决这一经典PCB设计软件的兼容性问题,提升工作效率。

m3n5b7v8c9x的博客 796

信息安全-入侵检测技术原理与应用

入侵检测技术原理与应用、入侵检测概述、入侵检测技术、入侵检测系统组成与分类、入侵检测系统主要产品与技术指标、入侵检测系统应用

我的个人博客 1万+

Python网络编程-Tcp

Python网络编程-Tcp24 网络编程-TCP24.1 TCP和UDP24.2 TCP网络编程24.2.1 tcp服务器端程序24.2.2 Tcp客户端程序24.3 Tcp服务端和客户端程序示例24.3.1 简单的一对一Tcp通信程序24.3.2 多对多的Tcp网络通信24.4 SocketServer模块 24 网络编程-TCP 在网络中,由IP地址可以唯一确定一台主机。但真正实现网络通信时并不是主机间一对一的通信,而是运行在各个主机上的应用程序(进程或线程)多对多的相互交换信息和数据。 网络通信的各

网络架构 884

f103vet6 SD卡SDIO+DMA配置避坑指南:从初始化卡死到稳定读写的全流程解析

本文详细解析STM32F103VET6芯片SD卡SDIO与DMA配置中的常见问题,从初始化卡死到读写不稳定的全流程解决方案。重点分析总线宽度配置、时钟分频调整及DMA通道管理技巧,帮助开发者避开常见陷阱,实现稳定高效的数据存储。

u0v1w2x3的博客 666

Python TCP 网络编程

Python TCP 网络编程 socket通信创建过程 首先:创建Socket,涉及到的主要参数有:domain、type、protocal。 domain是协议域,其中AF_INET->IPv4;AF_INET6->IPv6 。 type对应socket类型,SOCK_STREAM->TCP;SOCK_DGRAM->UDP。 server端编程: import socket #1创建一个socket server =s...

qy670752334的专栏 243

Ubuntu20.04 安装 MATLAB R2023b 常见问题及解决方案

本文提供了Ubuntu20.04系统上安装MATLAB R2023b的完整指南,包括系统要求检查、依赖项安装、详细安装步骤及常见问题解决方案。特别针对GTK模块加载失败、OpenGL图形加速问题和中文显示乱码等常见问题提供了有效解决方法,帮助用户顺利完成安装并优化使用体验。

weixin_42619061的博客 483

TI理想二极管在冗余电源中应用实例

深入探讨理想二极管如何提升冗余电源系统的效率与可靠性,通过实际应用案例展示其在电流隔离和自动切换中的优势,帮助工程师优化电源架构设计。

weixin_30653091的博客 987

掌握Python网络编程:从TCP到UDP

本文介绍了Python网络编程的基础知识,包括TCP和UDP协议的工作原理、Python中常用的网络编程库以及如何使用这些库进行网络通信。网络编程是当今软件开发中非常重要的技能之一,掌握Python网络编程将为开发者的职业生涯提供更多的机会和可能性。本文将介绍Python网络编程的基础知识,从TCP到UDP,帮助读者逐步掌握网络编程的核心技能。本文将介绍Python网络编程的基础知识,包括TCP和UDP协议的工作原理、Python中常用的网络编程库以及如何使用这些库进行网络通信。

weixin_71166183的博客 517

大厂校招:星宸科技嵌入式面试及参考答案(5万字长文)

当一个新的硬件设备被插入系统时,内核会发送一个设备事件通知 udev,udev 会根据设备的属性和规则,为该设备创建一个合适的设备文件。通过去除不必要的驱动程序、禁用不需要的功能、选择合适的内核配置选项、优化内核编译选项和定制内核模块等方法,可以减小内核的大小和复杂性,提高系统的性能和稳定性。上半部通常是在中断关闭的情况下执行的,以确保中断处理的原子性。处理碎片化内存是内存管理中的一个重要问题,可以采用内存压缩、内存池管理、伙伴系统、首次适应算法和最佳适应算法等方法来减少内存碎片的产生,提高内存的利用率。

大模型大数据攻城狮的专栏 2927

基于Tcp和UDP的python网络编程案例详解

文章目录TCP和UDP网络编程1.通信协议介绍2.TCP协议和UDP协议3.Socket(套接字)4.TCP简单网络编程5.UDP简单网络编程 TCP和UDP网络编程 1.通信协议介绍 (1)定义:网络通信协议是一种网络通用语言,为连接不同操作系统和不同硬件体系结构的互联网络引提供通信支持,是一种网络通用语言。 (2)网络通信协议由三个要素组成。 语义,解释控制信息每个部分的意义。它规定了需要发出何种控制信息,以及完成的动作与做出什么样的响应。 语法,用户数据与控制信息的结构与格式,以及数据出现的顺序。 时

qq_44176343的博客 1272

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

Python >>> TCP 网络编程

附上廖雪峰老师的web: https://www.liaoxuefeng.com/wiki/1016959663602400/1017787663253120 此处的python 网络编程主要指的是TCP 编程 Socket 是网络编程的一个抽象概念。 通常我们用一个Socket 表示“打开了一个网络链接”,而打开一个Socket 需要知道目标计算机的IP 地址和端口号,再指定协议类型即可。(...

原谅我这一生不羁放纵爱自由 635

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Python 网络编程-TCP/UDP编程

用TCP协议进行Socket编程在Python中十分简单,对于客户端,要主动连接服务器的IP和指定端口,对于服务器,要首先监听指定端口,然后,对每一个新的连接,创建一个线程或进程来处理。但是服务器还需要同时响应多个客户端的请求,所以,每个连接都需要一个新的进程或者新的线程来处理,否则,服务器一次就只能服务一个客户端了。答案是作为服务器,提供什么样的服务,端口号就必须固定下来。是一个特殊的IP地址,表示本机地址,如果绑定到这个地址,客户端必须同时在本机运行才能连接,也就是说,外部的计算机无法连接进来。

分享编程知识与技巧 致力于技术交流与学习 找我合作私聊 有偿解决计算机问题 1182

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Python 网络编程:TCP 与 UDP 协议详解及实战代码

在万物互联的时代,网络编程已成为开发者必备的核心技能。Python 凭借其简洁优雅的语法和强大的标准库支持,为网络应用开发提供了高效解决方案。本文将深入剖析 TCP 和 UDP 两大核心传输协议,通过代码实例演示其在 Python 中的具体实现,助力开发者构建稳定可靠的网络应用。

qq_63910171的博客 2371

Python网络编程之TCP协议(一)

TCP(Transmission Control Protocol,传输控制协议)是互联网的核心协议之一,提供了一种面向连接、可靠的字节流服务。与UDP不同,TCP注重数据完整性和顺序,确保数据在传输过程中不会丢失或乱序。本文将详细介绍TCP协议,包括其中涉及到的各种概念。目录前言IP地址的概念1. IP 地址的概念2. IP 地址的表现形式3. 查看 IP 地址4. 检查网络是否正常端口和端口号1. 问题思考2. 什么是端口3. 什么端口号4. 端口和端口号的关系5. 端口号的分类了解TCP。

专注Rust编程与技术分享,涵盖C++、Python等开发实战,新手友好,专注实战,助力编程成长。 13万+

python网络编程与使用TCP协议实现聊天室

网络编程 网络编程从大的方面说就是对信息的发送到接收,中间传输为物理线路的作用。 网络编程最主要的工作就是在发送端把信息通过规定好的协议进行组装包,在接收端按照规定好的协议把包进行解析,从而提取出对应的信息,达到通信的目的。中间最主要的就是数据包的组装,数据包的过滤,数据包的捕获,数据包的分析,当然最后再做一些处理,代码、开发工具、数据库、服务器架设和网页设计等。 套接字( Socket)是网络通信的关键,套接字也是应用程序和网络协议的接口。套接字由IP和端口号组成。网络层通信主要由TCP和UDP两种通讯。

个人学习笔记库,一篇一篇记录成长的足迹 6268

python 监听tcp端口_廖雪峰的Python系列教程(77)——网络编程TCP编程

TCP编程Socket是网络编程的一个抽象概念。通常我们用一个Socket表示“打开了一个网络链接”,而打开一个Socket需要知道目标计算机的IP地址和端口号,再指定协议类型即可。客户端 大多数连接都是可靠的TCP连接。创建TCP连接时,主动发起连接的叫客户端,被动响应连接的叫服务器。举个例子,当我们在浏览器中访问新浪时,我们自己的计算机就是客户端,浏览器会主动向新浪的服务器发起连接。...

weixin_35225189的博客 8526
上一篇: 网络概念
下一篇: python -- 网络编程(UDP编程)
鹿夏
博客等级 码龄8年 24粉丝 105原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值