网络编程——总结

网络编程总复习

1.网络编程

  • 软件开发架构

    • c/s架构:

      ? c: 客户端

      ? s: 服务端

    • b/s架构

      ? b: 浏览器

      ? s: 服务器

服务端:24 H 不间断提供服务

客户端: 需要时找服务器提供服务

网络编程》》》》》》学习cs架构软件

并发编程:前端,数据库,框架》》》》》》开发bs架构软件

实现网络通信的前提:物理连接介质

统一的标准:协议

2、OSI 七层协议

'''
应用层*
表示层
会话层
传输层*
网络层*
数据链路层*
物理链路层*
'''

  • 物理链路层:
  • 实现计算机之间物理连接,传输的都是010101010的二进制
  • 基于电信号工作原理:只有高低电平
  • 数据链路层(以太网协议):通讯方式基本靠吼
    • 规定了二进制的数据分组方式
    • 规定每个接入互联网的设备都必须有一块网卡
      • 每块网卡都必须有世界唯一的mac地址(通常由12位16进制数表示(前六位是厂商编号,后六位是流水线号))
  • 网络层(IP协议):
    • 规定了每个计算机都必须有IP(ipv4和ipv6)
    • ip地址能够唯一标识互联网中独一无二的一台机器
  • 传输层(端口协议):TCP,UDP基于端口工作的协议
    • 计算机应用程序与应用程序之间的通讯
    • 端口(port):唯一标识一台计算机上的某一个基于网络的通讯的协议
      '''
          端口范围:0~65535(动态分配)
              注意:0~1024通常是归操作系统分配的端口号
              通常情况下,我们写的软件端口号建议起在8000之后
              flask框架默认端口5000
              django框架默认端口8000
              mysql数据库默认端口3306
              redis数据库默认端口6379
      '''
      
      
TCP(流式协议,可靠协议)
    三次握手四次挥手

?

UDP协议(数据报协议)
    无需建立双向连接,并且传输数据不可靠,可能会出现丢包的情况
    通信速度比较快,但是发送的数据不会在内存中保留!
qq用的就是udp协议

3、socket层

  • 什么是socket层?

    • socket 是 应用层和tcp/ip协议之间通讯的抽象层,是一组接口

  • socket工作流程
    # 服务端:
    '''
    服务器端先初始化socket,然后与端口绑定(bind),对端口进行监听(listen)
    调用(accept)阻塞,等待客户端连接。
    '''
    # 客户端:
    '''
    客户端初始化socket,然后连接服务器(connect)
    '''
    # 通讯连接
    '''
    连接成功,客户端与服务器端的连接就建立好了,客户端发送数据请求,服务端接收并且处理请求,然后把回应数据发送给客户端回应
    客户端读取数据,关闭连接,完成一次交互
    '''

  • 服务端套接字函数
s.bind()    绑定(主机,端口号)到套接字
s.listen()  开始TCP监听
s.accept()  被动接受TCP客户的连接,(阻塞式)等待连接的到来
  • 客户端套接字函数
s.connect()     主动初始化TCP服务器连接
s.connect_ex()  connect()函数的扩展版本,出错时返回出错码,而不是抛出异常
  • 公共端套接字函数
s.recv()            接收TCP数据
s.send()            发送TCP数据(send在待发送数据量大于己端缓存区剩余空间时,数据丢失,不会发完)
s.sendall()         发送完整的TCP数据(本质就是循环调用send,sendall在待发送数据量大于己端缓存区剩余空间时,数据不丢失,循环调用send直到发完)
s.recvfrom()        接收UDP数据
s.sendto()          发送UDP数据
s.getpeername()     连接到当前套接字的远端的地址
s.getsockname()     当前套接字的地址
s.getsockopt()      返回指定套接字的参数
s.setsockopt()      设置指定套接字的参数
s.close()           关闭套接字
  • socket (TCP)模块程序

# 服务端
import socket

# 指定端口和每次数据长度
IP_PORT = ('127.0.0.1', 8080)  # 电话卡
BUFSIZE = 1024

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # 买电话

server.bind(IP_PORT)  # 插电话卡
server.listen(5)  # 待机

while True:  # 接收连接循环,可以不停的接电话
    conn, addr = server.accept()  # 接电话 阻塞:等待客户端连接

    while True:  # 新增接收连接的循环,可以不断的通讯
        try:
            msg = conn.recv(BUFSIZE)  # 听电话
            if len(msg) == 0: break  # 防止如果正在连接次client断开,recv发生死循环
            print(msg)

            conn.send(msg.upper()) # 发消息

        except ConnectionResetError:
            break
    conn.close()
server.close()
# 客户端
import socket

IP_PORT = ('127.0.0.1', 8080)  # 电话卡
BUFSIZE = 1024

client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 买手机

client.connect(IP_PORT) # 插卡

while True: # 循环连接

    msg = input('请输入你:').strip()
    if len(msg) == 0: continue
    client.send(msg.encode('utf-8')) # 发送给服务端

    serverback=client.recv(BUFSIZE) # 接收服务端反馈
    print(serverback.decode('utf-8'))

s.close()

  • 粘包问题

    注:只有tcp才有粘包问题,因为TCP协议是流式协议

    • 什么是粘包:

      • 所谓粘包问题主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的
    • 粘包发生的情况:
      • 发送端需要等缓冲区满才发送出去,造成粘包(发送数据时间间隔很短,数据了很小,会合到一起,产生粘包)
      • 接收方不及时接收缓冲区的包,造成多个包接收(客户端发送了一段数据,服务端只收了一小部分,服务端下次再收的时候还是从缓冲区拿上次遗留的数据,产生粘包)
  • 粘包的解决方法
    • 发送数据直接先告诉对方数据大小
    • 利用struct模块制定消息传递协议
  • 利用struct 解决方法
  • 发送时
    • 先制作报头字典,字典里包括:真实数据的信息,然后利用json序列化,
    • 利用struct进行打包成4个字节的报头
    • 先发送报头长度
    • 编码报头内容发送
    • 最后发送真实内容
  • 接收时
    • 先接收报头长度,用struct取出来
    • 根据报头长度接收报头内容,然后编码,反序列化
    • 从反序列化的结果中抽取带去的数据详细信息,然后去真实的数据内容
  • 案例:利用socket发送大文件
# 客户端
import socket
import struct
import json
import os

IP_PORT = ('127.0.0.1',8080)
client = socket.socket()
client.connect(IP_PORT)

file_path = r'F:\python_s7\网络编程复习\a'
file_size = os.path.getsize(file_path)

dic = {
    'file_name': 'b',
    'file_siz': file_size,
}
# json序列化
header_json = json.dumps(dic)
header_bytes = header_json.encode('utf-8')

# 制作字典报头
header = struct.pack('i',len(header_bytes))

# 发送报头
client.send(header)

# 发送字典数据
client.send(header_bytes)

# 发送真实内容
with open(file_path,'rb')as f:
    for line in f:
        client.send(line)
# 服务端
import socket
import json
import struct

IP_PORT = ('127.0.0.1',8080)
server = socket.socket()
server.bind(IP_PORT)
server.listen(5)

while True:
    conn,addr = server.accept()
    while True:
        try:
            header = conn.recv(4)
            if len(header)==0:break
            dic_len = struct.unpack('i',header)[0]
            dic = json.loads(conn.recv(dic_len).decode('utf-8'))

            file_name = dic['file_name']
            file_size = dic['file_size']
            recv_size =  0
            with open(file_name,'wb') as f :
                while recv_size<file_size:
                    data = conn.recv(1024)
                    f.write(data)
                    recv_size += len(data)

        except ConnectionResetError:
            break
  • socket(UDP)协议

"""
1.udp协议客户端允许发空
2.udp协议不会粘包
3.udp协议服务端不存在的情况下,客户端照样不会报错
4.udp协议支持并发

UDP叫数据报协议,意味着发消息都带有数据报头
udp的server不需要就行监听也不需要建立连接
在启动服务之后只能被动的等待客户端发送消息过来,客户端发送消息的时候,要带上服务端的地址
服务端在回复消息的时候,也需要带上客户端的地址
"""
# 服务端
import socket

server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(('127.0.0.1', 8080))

msg, addr = server.recvfrom(1024)
print(msg.decode('utf-8'))
server.sendto(b'hello', addr)

server.close()

#客户端
import socket

client = socket.socket(type=socket.SOCK_DGRAM)
server_addr = ('127.0.0.1', 8080)

client.sendto(b'hello server baby!', server_addr)
msg, addr = client.recvfrom(1024)
print(msg, addr)

4、socketsever 实现并发

# TCP socketserver使用
import socketserver

class MyTcpSever(socketserver.BaseRequestHandler):
    def handle(self):
        while True:
            try:
                # self.request 相当于conn对象
                data = self.request.recv(1204)
                if len(data) == 0: break
                print(data)
                self.request.send(data.upper())

            except ConnectionResetError:
                break

if __name__ == '__main__':
    sever = socketserver.ThreadingTCPServer(('127.0.0.1',8081),MyTcpSever)
    sever.serve_forever()
# Tcp客户端
import socket

client = socket.socket()
client.connect(('127.0.0.1',8080))

while True:
    client.send(b'hello')
    data = client.recv(1024)
    print(data)

# UDP socketserver使用
import socketserver

class MyUdpServer(socketserver.BaseRequestHandler):
    def handle(self):
        while True:
            data, sock = self.request
            print(data)
            sock.sendto(data.upper(), self.client_address)

if __name__ == '__main__':
    server = socketserver.ThreadingUDPServer(('127.0.0.1', 8080), MyUdpServer)
    server.serve_forever()

# UDP 客户端
import socket
import time

client = socket.socket(type=socket.SOCK_DGRAM)
server_addr = ('127.0.0.1',8080)

while True:
    client.sendto(b'hello',server_addr)
    data,addr = client.recvfrom(1024)
    print(data,addr)
    time.sleep(1)

    

原文地址:https://www.cnblogs.com/king-home/p/10885841.html

时间: 2024-11-06 09:33:48

网络编程——总结的相关文章

C#网络编程技术FastSocket实战项目演练

一.FastSocket课程介绍 .NET框架虽然微软提供了socket通信的类库,但是还有很多事情要自己处理,比如TCP协议需要处理分包.组包.粘包.维护连接列表等,UDP协议需要处理丢包.乱序,而且对于多连接并发,还要自己处理多线程等等.本期分享课程阿笨给大家带来的是来源于github开源Socket通信中间件:FastSocket,目的就是把大家从繁琐的网络编程技术中彻底地解放和释放出来. 阿笨只想安安静静的学习下网络编程技术Socket后,将学习的成果直接灵活的运用到自己的实际项目中去.

网络编程 -- RPC实现原理 -- RPC -- 迭代版本V1 -- 本地方法调用

网络编程 -- RPC实现原理 -- 目录 啦啦啦 V2--RPC -- 本地方法调用:不通过网络 入门 1. RPCObjectProxy rpcObjectProxy = new RPCObjectProxy(new LocalRPCClient()); : 绑定目标对象 2. IUserService userService = (IUserService) rpcObjectProxy.create(IUserService.class); :返回代理类 3. List<User> u

C#网络程序设计(1)网络编程常识与C#常用特性

    网络程序设计能够帮我们了解联网应用的底层通信原理!     (1)网络编程常识: 1)什么是网络编程 只有主要实现进程(线程)相互通信和基本的网络应用原理性(协议)功能的程序,才能算是真正的网络编程. 2)网络编程的层次 现实中的互联网是按照"TCP/IP分层协议栈"的体系结构构建的,因此程序员必须搞清楚自己要做的是哪个层次上的编程工作. TCP/IP协议体系的实现情况: 其中,网络接口层已经被大多数计算机生产厂家集成在了主板上,也就是经常所说的网卡(NIC).windows操

9. 网络编程:

网络编程: 端口: 物理端口: 逻辑端口:用于标识进程的逻辑地址,不同进程的标识:有效端口:0~65535,其中0~1024系统使用或保留端口. java 中ip对象:InetAddress. import java.net.*; class  IPDemo{ public static void main(String[] args) throws UnknownHostException{ //通过名称(ip字符串or主机名)来获取一个ip对象. InetAddress ip = InetA

物联网网络编程、Web编程综述

本文是基于嵌入式物联网研发工程师的视觉对网络编程和web编程进行阐述.对于专注J2EE后端服务开发的童鞋们来说,这篇文章可能稍显简单.但是网络编程和web编程对于绝大部分嵌入式物联网工程师来说是一块真空领域. 的确,物联网研发应该以团队协作分工的方式进行,所以有嵌入式设备端.网关.web前端.APP.后端开发等专属岗位.作为系统架构师,自然需要掌握各种岗位的关键技术.作为嵌入式工程师,掌握网络编程.web编程,能够极大地拓展自己的视野和架构思维,能够主动地对系统的各种协议和应用场景提出优化的见解

linux网络编程-(socket套接字编程UDP传输)

今天我们来介绍一下在linux网络环境下使用socket套接字实现两个进程下文件的上传,下载,和退出操作! 在socket套接字编程中,我们当然可以基于TCP的传输协议来进行传输,但是在文件的传输中,如果我们使用TCP传输,会造成传输速度较慢的情况,所以我们在进行文件传输的过程中,最好要使用UDP传输. 在其中,我们需要写两个程序,一个客户端,一个服务端,在一个终端中,先运行服务端,在运行客户端,在服务端和客户端都输入IP地址和端口号,注意服务端和客户端的端口号要相同,然后选择功能,在linux

UNIX网络编程卷1 回射客户程序 TCP客户程序设计范式

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 下面我会介绍同一个使用 TCP 协议的客户端程序的几个不同版本,分别是停等版本.select 加阻塞式 I/O 版本. 非阻塞式 I/O 版本.fork 版本.线程化版本.它们都由同一个 main 函数调用来实现同一个功能,即回射程序客户端. 它从标准输入读入一行文本,写到服务器上,读取服务器对该行的回射,并把回射行写到标准输出上. 其中,非阻塞式 I/O 版本是所有版本中执行速度最快的,

黑马程序员——网络编程篇

------- android培训.java培训.期待与您交流! ---------- 概述   1.网络模型        (1).OSI参考模型        (2).TCP/IP参考模型   2.网络通讯要素         (1).IP地址        (2).端口号         (3).传输协议    3.过程        1,找到对方IP. 2,数据要发送到对方指定的应用程序上.为了标识这些应用程序,所以给这些网络应用程序都用数字进行标识. 为了方便称呼这个数据,叫做端口(逻

网络编程TCP/IP实现客户端与客户端聊天

一.TCP/IP协议 既然是网络编程,涉及几个系统之间的交互,那么首先要考虑的是如何准确的定位到网络上的一台或几台主机,另一个是如何进行可靠高效的数据传输.这里就要使用到TCP/IP协议. TCP/IP协议(传输控制协议)由网络层的IP协议和传输层的TCP协议组成.IP层负责网络主机的定位,数据传输的路由,由IP地址可以唯一的确定Internet上的一台主机.TCP层负责面向应用的可靠的或非可靠的数据传输机制,这是网络编程的主要对象. 二.TCP与UDP TCP是一种面向连接的保证可靠传输的协议

(一)理解网络编程和套接字

学习<TCP/IP网络编程> 韩 尹圣雨 著 金国哲 译 套接字类似电话 一.服务器端套接字(listening套接字)---接电话套接字 ①调用socket函数---安装电话机 #include <sys/socket.h> int socket(int domain, int type, int protocol); //成功时返回文件描述符,失败时返回-1 ②调用bind函数---分配电话号码 #include <sys/socket.h> int bind(in