进程间通信(IPC -- InterProcess Communication)的五种方式

0. 前言

0.1 进程间通信的必要性
进程间空间独立,资源不共享,此时若需要在进程间数据传输,就需要用特定的手段进行数据通信。

0.2 常用的进程间通信方式
(1)管道(拓展:命名管道);(2)消息队列;(3)共享内存;(4)信号量;(5)套接字。

1. 管道通信(Pipe)

1.1 通信原理
在内存中开辟管道空间,生成管道操作对象,多个进程使用同一个管道对象进行读写,从而实现进程间的通信。

1.2 实现方法

from multiprocessing import Pipe

fd1,fd2 = Pipe(duplex = True)
功能:创建管道
参数:默认表示双向管道
如果duplex为False,表示单向管道
返回值:表示管道两端的读写对象
	   如果是双向管道均可读写
	   如果是单向管道,则fd1只读,fd2只写

fd.recv()
  功能:从管道获取内容
返回值:从管道获取到的数据

fd.send(data)
功能: 向管道写入内容
参数: 要写入的数据

1.3 示例代码

"""
pipe.py 管道操作
注意:
     1. multiprocessing中提供的通信只用于亲缘关系进程间通信
     2. 管道在父进程中创建,子进程从父进程中获取管道对象
"""
from multiprocessing import Process, Pipe

# app1可以使用app2提供的信息登录
def app1(fd1):
    print("启动app1,请求app2授权登录")
    # 写管道
    fd1.send("app1 可以用你的账号登录吗?")
    # 阻塞等待读取管道
    data = fd1.recv()
    # 如果管道中有数据(fd2发送了数据)
    if data:
        print("登录成功:", data)

def app2(fd2):
    print("启动app2")
    request = fd2.recv()  # 阻塞等待读取管道
    if request:
        print(request)
        fd2.send(("授权登录!"))  # 发送python数据类型

if __name__ == '__main__':
    fd1, fd2 = Pipe()
    p1 = Process(target=app1, args=(fd1,))
    p2 = Process(target=app2, args=(fd2,))
    p2.start()
    p1.start()
    p1.join()
    p2.join()

1.4 命名管道
相应文章:
(1)Python进程间通信之命名管道
注:FIFO – First Input First Output 先入先出
(2)Python进程间通信之命名管道(Windows)
代码示例

# server
import win32file
import win32pipe

PIPE_NAME = r'\\.\pipe\test_pipe'
PIPE_BUFFER_SIZE = 65535

while True:
    named_pipe = win32pipe.CreateNamedPipe(PIPE_NAME,
                                           win32pipe.PIPE_ACCESS_DUPLEX,
                                           win32pipe.PIPE_TYPE_MESSAGE | win32pipe.PIPE_WAIT | win32pipe.PIPE_READMODE_MESSAGE,
                                           win32pipe.PIPE_UNLIMITED_INSTANCES,
                                           PIPE_BUFFER_SIZE,
                                           PIPE_BUFFER_SIZE, 500, None)
    try:
        while True:
            try:
                win32pipe.ConnectNamedPipe(named_pipe, None)
                data = win32file.ReadFile(named_pipe, PIPE_BUFFER_SIZE, None)

                if data is None or len(data) < 2:
                    continue

                print 'receive msg:', data
            except BaseException as e:
                print "exception:", e
                break
    finally:
        try:
            win32pipe.DisconnectNamedPipe(named_pipe)
        except:
            pass


# client
import win32pipe, win32file
import time

PIPE_NAME = r'\\.\pipe\test_pipe'

file_handle = win32file.CreateFile(PIPE_NAME,
                                   win32file.GENERIC_READ | win32file.GENERIC_WRITE,
                                   win32file.FILE_SHARE_WRITE, None,
                                   win32file.OPEN_EXISTING, 0, None)
try:
    for i in range(1, 11):
        msg = str(i)
        print 'send msg:', msg
        win32file.WriteFile(file_handle, msg)
        time.sleep(1)
finally:
    try:
        win32file.CloseHandle(file_handle)
    except:
        pass

2. 消息队列(Queue)

2.1 通信原理
在内存中建立队列模型,进程通过队列将消息存入,或者从队列中取出消息,从而完成进程间的通信。

2.2 实现方法

from multiprocessing import Queue

q = Queue(maxsize=3)
功能:创建队列对象
参数:最多存放消息个数
返回值:队列对象

q.put(data, [block, timeout])
功能:向队列存入消息
参数:
data -- 要存入的内容
block -- 设置是否阻塞 False为非阻塞
timeout -- 超时检测
返回值:返回获取到的内容

q.full() -- 判断队列是否为满
q.empty() -- 判断队列是否为空
q.qsize() -- 获取队列中消息个数
q.close() -- 关闭队列

2.3 示例代码

"""
消息队列演示
注意: 消息存入与取出的关系为: 先入先出
"""
from multiprocessing import Queue, Process
from random import randint

def request(q):
    for i in range(10):
        x = randint(1, 100)
        y = randint(1, 100)
        print('write: ', (x, y))
        q.put((x, y))  # 写消息队列

def handle(q):
    read_data = []
    while not q.empty():
        data = q.get()  # 读消息队列
        print('read: ', (data[0], data[1]))
        print("x + y= ", data[0] + data[1])
        read_data.append(data)
    print('read_data---', read_data)

if __name__ == '__main__':
    # 创建队列
    q = Queue(15)  # 最多存储15个消息(该数≥request(q)中的range(10),可以保证通信顺畅,不丢失数据)

    p1 = Process(target=request, args=(q,))
    p2 = Process(target=handle, args=(q,))
    p1.start()
    p2.start()
    p1.join()
    p2.join()
    q.close()

3. 共享内存

3.1 通信原理
在内存中开辟一块空间,进程可以写入内容和读取内容,从而完成通信,但是每次写入内容会覆盖之前内容。

3.2 实现方法
在这里插入图片描述

from multiprocessing import Value, Array

obj = Value(ctype,data)
功能:开辟共享内存
参数:ctype  表示共享内存空间类型 'i'  'f'  'c'
      data   共享内存空间初始数据
返回值:共享内存对象

obj.value  对该属性的修改查看即对共享内存读写


obj = Array(ctype,data)
功能: 开辟共享内存空间
参数: ctype  表示共享内存数据类型
      data   整数则表示开辟空间的大小,其他数据类型表示开辟空间存放的初始化数据
返回值:共享内存对象

Array共享内存读写: 通过遍历obj可以得到每个值,直接可以通过索引序号修改任意值。

* 可以使用obj.value直接打印共享内存中的字节串

3.3 示例代码

"""
value.py 开辟共享内存空间
注意: 共享内存中只能有一个值
"""
from multiprocessing import Process, Value
import time
import random

def man(money):
    for i in range(30):
        time.sleep(0.2)
        # 修改共享内存
        money.value += random.randint(1, 1000)

def girl(money):
    for i in range(30):
        time.sleep(0.15)
        # 修改共享内存
        money.value -= random.randint(100, 800)

if __name__ == '__main__':
    # 创建共享内存
    money = Value('i', 5000)
    p1 = Process(target=man, args=(money,))
    p2 = Process(target=girl, args=(money,))
    p1.start()
    p2.start()
    p1.join()
    p2.join()
    print("一个月余额:", money.value)  # 读取共享内存
"""
array.py
共享内存中存放列表,字节串
"""
from multiprocessing import Process, Array

def fun(msg):
    # 共享内存对象可以迭代
    for i in msg:
        print(i)
    msg[0] = b'y'  # 修改共享内存

if __name__ == '__main__':
    # 创建共享内存
    # shm = Array('i',[1,2,3,4])
    # shm = Array('i',4) # 开辟4个整型的列表空间
    msg = Array('c', b'hello')
    p = Process(target=fun, args=(msg, ))
    p.start()
    p.join()
    for i in msg:
        print(i)
    print(msg.value)  # b'yello' 整体打印字节串 

4. 信号量(信号灯集)

4.1 通信原理
给定一个数量,对多个进程可见。多个进程都可以操作该数量增减,并根据数量值决定自己的行为。

4.2 实现方法

from multiprocessing import Semaphore

sem = Semaphore(num)
功能:创建信号量对象
参数:信号量的初始值
返回值:信号量对象

sem.acquire() -- 将信号量减1,当信号量为0时阻塞
sem.release() -- 将信号量加1
sem.get_value() -- 获取信号量数量

4.3 示例代码

"""
sem.py
信号量演示
注意:信号量可以当作是一种资源,执行任务时需要消耗信号量资源,
这样可以控制进程执行行为
"""
from multiprocessing import Process,Semaphore
from time import sleep
import os

# 任务函数(系统中最多能够同时运行3个该任务)
def handle(sem):
    sem.acquire()  # 消耗一个信号量
    print("%s 执行任务" % os.getpid())
    sleep(2)
    print("%s拯救了宇宙" % os.getpid())
    sem.release()  # 增加一个信号量

if __name__ == '__main__':
    # 创建信号量资源
    sem = Semaphore(3)  # 信号量资源有3个
    jobs = []
    for i in range(10):
        p = Process(target=handle, args=(sem,))
        jobs.append(p)
        p.start()

    for i in jobs:
        i.join()
    print(sem.get_value())  # 3

5. socket套接字

5.1 套接字介绍

  1. 套接字 : 实现网络编程进行数据传输的一种技术手段

  2. Python实现套接字编程:import socket

  3. 套接字分类

流式套接字(SOCK_STREAM): 以字节流方式传输数据,实现tcp网络传输方案。(面向连接–tcp协议–可靠的–流式套接字)
数据报套接字(SOCK_DGRAM):以数据报形式传输数据,实现udp网络传输方案。(无连接–udp协议–不可靠–数据报套接字)

5.2 tcp套接字编程

5.2.1 服务端流程
在这里插入图片描述

5.2.2 示例代码

# 服务器端
from socket import *
from time import ctime

HOST = ''
PORT = 21567
BUFSIZ = 1024
ADDR = (HOST,PORT)

tcpSerSock = socket(AF_INET,SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(5)

while True:
    print('waiting for connection...')
    tcpCliSock, addr = tcpSerSock.accept()
    print('...connnecting from:', addr)

    while True:
        data = tcpCliSock.recv(BUFSIZ)
        if not data:
            break
        #tcpCliSock.send('[%s] %s' %(bytes(ctime(),'utf-8'),data))
        tcpCliSock.send(('[%s] %s' % (ctime(), data)).encode())
    tcpCliSock.close()
tcpSerSock.close()

5.2.3 具体流程介绍

  1. 创建套接字
sockfd=socket.socket(socket_family=AF_INET,socket_type=SOCK_STREAM,proto=0)
功能:  创建套接字
参数:  socket_family  网络地址类型 AF_INET表示ipv4
	   socket_type  套接字类型 SOCK_STREAM(流式)  SOCK_DGRAM(数据报)
	   proto  通常为0  选择子协议
返回值:套接字对象
  1. 绑定地址

本地地址 : ‘localhost’ , ‘127.0.0.1’
网络地址 : ‘172.40.91.185’
自动获取地址: ‘0.0.0.0’

在这里插入图片描述

sockfd.bind(addr)
功能: 绑定本机网络地址
参数: 二元元组 (ip,port)  ('0.0.0.0',8888)
  1. 设置监听
sockfd.listen(n)
功能 : 将套接字设置为监听套接字,确定监听队列大小
参数 : 监听队列大小
  1. 等待处理客户端连接请求
connfd,addr = sockfd.accept()
功能: 阻塞等待处理客户端请求
返回值: connfd  客户端连接套接字
         addr   连接的客户端地址
  1. 消息收发
data = connfd.recv(buffersize)
功能 : 接受客户端消息
参数 :每次最多接收消息的大小
返回值: 接收到的内容

n = connfd.send(data)
功能 : 发送消息
参数 :要发送的内容  bytes格式
返回值: 发送的字节数
  1. 关闭套接字
sockfd.close()
功能:关闭套接字

5.2.4 客户端流程
在这里插入图片描述

5.2.5 示例代码

# 客户端
from socket import *

HOST = '127.0.0.1' # or 'localhost'
PORT = 21567
BUFSIZ = 1024
ADDR = (HOST,PORT)

tcpCliSock = socket(AF_INET,SOCK_STREAM)
tcpCliSock.connect(ADDR)
while True:
     data1 = input('>')
     #data = str(data)
     if not data1:
         break
     tcpCliSock.send(data1.encode())
     data1 = tcpCliSock.recv(BUFSIZ)
     if not data1:
         break
     print(data1.decode('utf-8'))
tcpCliSock.close()

5.2.6 具体流程介绍

  1. 创建套接字

注意:只有相同类型的套接字才能进行通信

  1. 请求连接

sockfd.connect(server_addr)
功能:连接服务器
参数:元组 服务器地址

  1. 收发消息

注意: 防止两端都阻塞,recv send要配合

  1. 关闭套接字

5.2.7 tcp 套接字数据传输特点

  • tcp连接中当一端退出,另一端如果阻塞在recv,此时recv会立即返回一个空字串。
  • tcp连接中如果一端已经不存在,仍然试图通过send发送则会产生BrokenPipeError
  • 一个监听套接字可以同时连接多个客户端,也能够重复被连接

5.2.8 网络收发缓冲区

  1. 网络缓冲区有效的协调了消息的收发速度
  2. send和recv实际是向缓冲区发送接收消息,当缓冲区不为空recv就不会阻塞。

5.2.9 tcp粘包

原因:tcp以字节流方式传输,没有消息边界。多次发送的消息被一次接收,此时就会形成粘包。
影响:如果每次发送内容是一个独立的含义,需要接收端独立解析此时粘包会有影响。
处理方法

  1. 人为的添加消息边界
  2. 控制发送速度

5.2.10 Socket tcp 文件传输代码示例
server.py

import socket
import struct
import json
import hashlib

server = socket.socket()
server.bind(("127.0.0.1", 7000))
server.listen(5)
while 1:
    request, address = server.accept()
    print('接收链接', address)
    while 1:
        cmd = request.recv(4)
        if cmd.decode('utf8') == 'exit':
            break
        json_len = struct.unpack('i', cmd)[0]
        json_data = json.loads(request.recv(json_len))
        action = json_data['action']
        filename = json_data['filename']
        filelen = json_data['filelen']
        received_len = 0
        print(json_data)
        md5 = hashlib.md5()
        with open('data/'+filename, 'wb') as f:
            while received_len < filelen:
                if filelen - received_len >= 1024:
                    readlen = 1024
                else:
                    readlen = filelen - received_len
                filedata = request.recv(readlen)
                f.write(filedata)
                md5.update(filedata)
                received_len += len(filedata)
                print(f'已完成{received_len}/总大小{filelen}')
        print('传输完成')
        recv_md5 = request.recv(32)
        if recv_md5.decode('utf-8') == md5.hexdigest():
            print('文件正常传输')
        else:
            print('文件异常')
    request.close()
    print('断开链接', address)

client.py

import socket
import struct
import json
import os
import hashlib

client = socket.socket()
client.connect(('127.0.0.1', 7000))
while 1:
    cmd = input(">>>")
    if cmd == 'exit':
        client.send(cmd.encode('utf8'))
        break
    action, filename = cmd.split()
    command = {'action':action,
               'filename':os.path.basename(filename),
               'filelen':os.path.getsize(filename),}

    json_data = json.dumps(command).encode('utf8')
    header = struct.pack('i', len(json_data))
    client.send(header)
    client.send(json_data)
    md5 = hashlib.md5()
    with open(filename, 'rb') as f:
        for line in f:
            client.send(line)
            md5.update(line)
    client.send(md5.hexdigest().encode('utf-8'))
    print("发送完成")
client.close()

5.2.11 Socket tcp 大型数组传输代码示例(思路仅供参考,不推荐,因为接收速度太慢)
server.py

import time
from socket import *
import struct
import json
import hashlib
import numpy as np

server = socket(AF_INET, SOCK_STREAM)
server.bind(("127.0.0.1", 7000))
server.listen(5)
while 1:
    client, address = server.accept()
    print('接收链接:', address)

    cmd0 = client.recv(1)  # 是否关闭服务端
    # 关闭服务端和客户端
    # print('cmd0---', cmd0)
    if cmd0.decode('utf-8') == '1':
        client.close()
        server.close()
        exit(0)
    else:
        cmd1 = client.recv(4)
        # print('cmd1---', cmd1)
        json_len = struct.unpack('i', cmd1)[0]

        json_data = json.loads(client.recv(json_len).decode('utf-8'))
        print('json_data---', json_data['array_len'])

        array_len = json_data['array_len']
        array_type = json_data['array_dtype']
        print(np.dtype(array_type))
        received_len = 0
        received_array = b''
        result = []
        while received_len < array_len:
            if array_len - received_len >= 8192:
                r_len = 8192
            else:
                r_len = array_len - received_len

            # r_time_0 = time.time()
            received_data = client.recv(r_len)
            # r_time_1 = time.time()
            # print('r_time: ', r_time_1-r_time_0)
            # a_time_0 = time.time()
            # result.append(received_data)
            received_array += received_data  # 该步慢了容易出问题~接收得快,但拼接慢
            # a_time_1 = time.time()
            # print('add time: ', a_time_1-a_time_0)

            received_len += len(received_data)  # 这一部很关键,说明recv()的不一定等于r_len

            # percent = received_len/array_len*100
            # print(percent)
        # received_array = ''.join(str(result))
        print(len(received_array))
        # received_array = bytes(received_array)
        # print('len(received_array)---', len(received_array))

        # print('received_array---', received_array)
        print('received_len---', received_len)
        print('array len ', array_len)
        # array = np.fromstring(received_array, dtype=np.float64)
        array = np.fromstring(received_array, dtype=np.dtype(array_type))
        # array = received_array

        shape = json_data['array_shape']
        print(array.size)
        array = array.reshape(shape)
        # print(array)
        client.close()
        print('断开链接', address)

client.py

from socket import *
import struct
import json
import os
import numpy as np
import argparse
import sys

def manage_client(cmd, array):
    client = socket(AF_INET, SOCK_STREAM)
    client.connect(('127.0.0.1', 7000))
    # 发送是否退出服务端和客户端的指令
    client.send(cmd[0].encode('utf-8'))

    wanted_class = cmd[1]
    
    # 将数组统一为np.float64,方便计算数组占的内存大小和后续检测
    # array = array.astype(np.float64)
    # array = array.squeeze()

    array_shape = array.shape
    # array_len = array_shape[0] * array_shape[1] * 8
    # print(array_len)
    b_array = array.tostring()

    command = {'wanted_class': wanted_class,
               'array_shape': array_shape,
               'array_dtype': array.dtype.name,
               # 'array_len': array_len,
               'array_len': len(b_array),
               }
    json_data = json.dumps(command).encode('utf-8')
    header = struct.pack('i', len(json_data))
    print('len(json_data)', len(json_data))
    print('header---', header)

    client.send(header)
    client.send(json_data)

    # 传输数组
    client.send(b_array)
    
    print("发送完成")
    client.close()


if __name__ == '__main__':
    # array = np.array([[1, 2], [3, 4], [5, 6]], dtype=np.float64)
    array = np.load('npys/demo.npy')

    print(array.size)
    # array = np.ones((100, 200), np.int32)
    # 3种情况
    # 1. 关闭服务端、客户端 python client.py -e 1
    # 2. 执行某操作 python client.py -e 0 -c dog
    import sys
    sys.argv = ['client.py', '-e', '0', '-c', 'dog']
    parser = argparse.ArgumentParser()
    parser.add_argument("-e", "--exit", default="1", help="ask the server to exit, 0--not exit, 1--exit")
    parser.add_argument("-c", "--class_p", default=None, help="wanted class to predict")
    args = parser.parse_args()
    cmd = [args.exit, args.class_p]
    manage_client(cmd, array)

涉及新知识点汇总:

1. struct
原理: 将一组简单数据进行打包,转换为bytes格式发送。或者将一组bytes格式数据,进行解析。

接口使用:
Struct(fmt)
功能: 生成结构化对象
参数:fmt  定制的数据结构

import struct
struct.pack(v1,v2,v3....)
功能: 将一组数据按照指定格式打包转换为bytes
参数:要打包的数据
返回值: bytes字节串

struct.unpack(bytes_data)
功能: 将bytes字节串按照指定的格式解析
参数: 要解析的字节串
返回值: 解析后的内容

struct.pack(fmt,v1,v2,v3...)
struct.unpack(fmt,bytes_data)

在这里插入图片描述

2. tostring,tobytes,fromstring, frombuffer

# 把数组array转为bytes二进制类型,通过len(new_array)可以获得new_array的占内存大小;
new_array = array.tostring()  
tobytes() --同tostring()

# 字符串转为bytes:
a = 'hello world!'
bytes_a = b'hello world!'

# 由bytes转为数组,需注明数组元素类型
result = numpy.fromstring(new_array, dtype = numpy.int8)  

frombuffer – 顺藤摸瓜-mnist数据集的补充,二进制buffer读取,numpy的frombuffer方法等

3. json
# json.dumps()用于将字典形式的数据转化为字符串,json.loads()用于将字符串形式的数据转化为字典,
a = {}
# 字典形式数据 --> 字符串
json_data = json.dumps(a)
# 字符串形式数据 --> 字典
dict_data = json.loads(json_data)
4. hashlib
转载:https://blog.csdn.net/syousetu/article/details/107065140
import hashlib         #导入hashlib模块

md = hashlib.md5()     # 获取一个md5加密算法对象
md.update('how to use md5 in hashlib?'.encode('utf-8'))  # 制定需要加密的字符串
print(md.hexdigest())  # 获取加密后的16进制字符串
5. sys.argv
在xxx.py文件中使用argparse.ArgumentParser(),通过终端python xxx.py -a yyy -b zzz运行,

可替换为:在xxx.py文件中使用argparse.ArgumentParser()之前添加sys.argv = ['xxx.py', '-a', 'yyy', '-b', 'zzz'],然后pycharm直接run即可

5.3 UDP套接字编程

5.3.1 服务端流程
在这里插入图片描述

5.3.2 示例代码

"""
udp_server.py udp服务端
"""

from socket import *

# 创建UDP套接字
sockfd = socket(AF_INET,SOCK_DGRAM)

# 绑定地址
server_addr = ('0.0.0.0', 8888)
sockfd.bind(server_addr)

# 循环收发
while True:
    data,addr = sockfd.recvfrom(1024)
    print("收到的消息:", data.decode())
    sockfd.sendto(b'Thanks', addr)

# 关闭套接字
sockfd.close()

5.3.3 具体流程介绍

  1. 创建数据报套接字
sockfd = socket(AF_INET,SOCK_DGRAM)
  1. 绑定地址
sockfd.bind(addr)
  1. 消息收发
data,addr = sockfd.recvfrom(buffersize)
功能: 接收UDP消息
参数: 每次最多接收多少字节
返回值: data  接收到的内容
	    addr  消息发送方地址

n = sockfd.sendto(data,addr)
功能: 发送UDP消息
参数: data  发送的内容 bytes格式
	  addr  目标地址
返回值:发送的字节数
  1. 关闭套接字
sockfd.close()

5.3.4 客户端流程
在这里插入图片描述

5.3.5 示例代码

"""
udp_client.py  udp客户端
"""

from socket import *

# 服务器地址
ADDR = ('127.0.0.1',8888)

# 创建套接字
sockfd = socket(AF_INET,SOCK_DGRAM)

# 循环发送消息
while True:
    data = input("Msg:")
    if not data:
        break
    sockfd.sendto(data.encode(),ADDR)
    msg,addr = sockfd.recvfrom(1024)
    print("From server:",msg.decode())

sockfd.close()
  1. 创建套接字
  2. 收发消息
  3. 关闭套接字

总结 :tcp套接字和udp套接字编程区别

  1. 流式套接字是以字节流方式传输数据,数据报套接字以数据报形式传输
  2. tcp套接字以字节流方式传输,会有粘包,udp套接字以数据报形式,有消息边界不会粘包
  3. tcp套接字保证消息的完整性,udp套接字则不能
  4. tcp套接字依赖listen accept建立连接才能收发消息,udp套接字则不需要
  5. tcp套接字使用send,recv收发消息,udp套接字使用sendto,recvfrom

5.4 socket套接字属性

示例代码

"""
套接字属性介绍
"""

from socket import *

# 创建套接字对象
s = socket(AF_INET,SOCK_STREAM)

# 设置端口立即重用
s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)

s.bind(('172.40.91.143',8888))
s.listen(3)
c,addr = s.accept()

print(s.type)  # 套接字类型
print(s.family) # 地址类型
print(s.getsockname()) # 绑定的地址
print(s.fileno()) # 文件描述符
print(c.getpeername())  # 获取连接端的地址

c.recv(1024)
【1】 sockfd.type  套接字类型

【2】 sockfd.family 套接字地址类型

【3】 sockfd.getsockname() 获取套接字绑定地址

【4】 sockfd.fileno() 获取套接字的文件描述符

【5】 sockfd.getpeername() 获取连接套接字客户端地址

【6】 sockfd.setsockopt(level,option,value)
         功能:设置套接字选项
		 参数: level  选项类别   SOL_SOCKET
			   option 具体选项内容
			   value  选项值

在这里插入图片描述

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值