网络编程知识点剖析

一. C/S 架构: Client / Server  客户端 / 服务端

    B/S 架构: Browser / Server  前端 / 服务端

二.网络编程通信流程.

  网卡   mac地址   IP地址   子网掩码   网关   DNS服务器  (进行域名(domain name)和与之相对应的IP地址 (IP address)转换的服务器。)  

  DHCP (自动分配IP)    NAT (Network Address Translation,网络地址转换)  端口   路由器

   交换机   集线器   广播 单播 广播风暴   arp协议(地址解析协议)    路由协议

三.网络通信协议

 1. osi七层:            tcp\ ip 五层:

      应用层              应用层  

      表示层              传输层

      会话层              网路层

      传输层              数据链路层

      网络层              物理层

      数据链路层

      物理层

  2. TCP\IP 协议存在 传输层   

    Tcp   : 面向连接,消息可靠,效率相对差,面向流的消息格式,无消息保护边界    

    Udp  : 面向无连接,消息不可靠,效率高,面向包的消息格式,有消息保护边界

    tcp三次握手:1.(client) > [SYN包 ]->(server)   请求建立连接

          2.(client) < [SYN/ACK] < (server)  severs收到syn 发送[SYN/ACK]确认包

          3.(client)> [ACK] >(server)  client收到[SYN/ACK] 在发一个[ACK]确认包

    tcp四次挥手:1.(client) > [ACK/FIN] >(server) 发送包 请求关闭

          2.(client) < [ACK] <(server)  收到包  同意关闭

          3.(client) <[ACK/FIN] <(server) 收到包   是否收到 同意关闭 消息 

          4.(client) > [ACK/FIN] >(server)  发送包  收到过程2的消息,

四.socket

  1. 服务端与客户端 手法消息 基本结构

server>>>>>>>>>>>>>>>>>

import socket
sk = socket.socket()
sk.bind((‘127.0.0.1‘,8898))  #把地址绑定到套接字
sk.listen()          #监听链接
conn,addr = sk.accept() #接受客户端链接
ret = conn.recv(1024)  #接收客户端信息
print(ret)       #打印客户端信息
conn.send(b‘hi‘)        #向客户端发送信息
conn.close()       #关闭客户端套接字
sk.close()        #关闭服务器套接字(可选)

client>>>>>>>>>>>>>>>>
import socket
sk = socket.socket()           # 创建客户套接字
sk.connect((‘127.0.0.1‘,8898))    # 尝试连接服务器
sk.send(b‘hello!‘)
ret = sk.recv(1024)         # 对话(发送/接收)
print(ret)
sk.close()            # 关闭客户套接字

tcp 服务端和客户端通信 基本代码

server>>>>>>>>>>>>>>>>>>>>>>>>

import socket
udp_sk = socket.socket(type=socket.SOCK_DGRAM)   #创建一个服务器的套接字
udp_sk.bind((‘127.0.0.1‘,9000))        #绑定服务器套接字
msg,addr = udp_sk.recvfrom(1024)
print(msg)
udp_sk.sendto(b‘hi‘,addr)                 # 对话(接收与发送)
udp_sk.close()                         # 关闭服务器套接字

client>>>>>>>>>>>>>>>>>>>>>>>>

import socket
ip_port=(‘127.0.0.1‘,9000)
udp_sk=socket.socket(type=socket.SOCK_DGRAM)
udp_sk.sendto(b‘hello‘,ip_port)
back_msg,addr=udp_sk.recvfrom(1024)
print(back_msg.decode(‘utf-8‘),addr)

udp

  2.缓冲区

     作用:  提高效率,将发送或者接受信息的过程与网络传输隔离开,解耦

    特性:  1.I/O缓冲区在每个TCP套接字中单独存在;
         2.I/O缓冲区在创建套接字时自动生成;
         3.即使关闭套接字也会继续传送输出缓冲区中遗留的数据;
         4.关闭套接字将丢失输入缓冲区中的数据。
    大小:  一般默认为 8K, 可以通过 getsockopt() 函数获取

  3.粘包

    TCP会粘包、UDP永远不会粘包

    粘包的两种现象: 

    1.连续发送小包并且间隔时间很短,就会发送两个消息合并在一起的情况,被一次接受了,(Nagel 优化算法导致的,            避免连续发送小包,影响传输xiaol)

    2.一次发送数据过大,对方一次未接受完导致下次接受的时候,连同第一次剩下的消息,一同接受了,导致粘包.

    解决粘包的方案: 

      原因是因为双方不知道对方发送的消息长度

    1.发送消息之前先发送消息的长度,然后收到对方的确认信息后再发送消息.

    2.通过struct模块,自定义包头,将消息长度打包成4个字节长度的信息,连同你要发送的数据,一起发送过去

      打包:pack(‘i‘,长度) 长度是个整数

      解包:unpack(‘i‘,接受的那4个字节),得到的是元祖

    Sendall(): 循环的send直到数据发送完毕.

    Socketsserver(): 实现tcp协议下,一个服务端可以同时和多个客户端进行通信.

import socket,struct,json
import subprocess
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)

phone.bind((‘127.0.0.1‘,8080))
phone.listen(5)

while True:
    conn,addr=phone.accept()
    while True:
        cmd=conn.recv(1024)
        if not cmd:break
        print(‘cmd: %s‘ %cmd)

        res=subprocess.Popen(cmd.decode(‘utf-8‘),
                             shell=True,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE)
        err=res.stderr.read()
        print(err)
        if err:
            back_msg=err
        else:
            back_msg=res.stdout.read()

        headers={‘data_size‘:len(back_msg)}
        head_json=json.dumps(headers)
        head_json_bytes=bytes(head_json,encoding=‘utf-8‘)

        conn.send(struct.pack(‘i‘,len(head_json_bytes))) #先发报头的长度
        conn.send(head_json_bytes) #再发报头
        conn.sendall(back_msg) #在发真实的内容

    conn.close()

解决粘包方案一 server

import socket
import struct,json
client= socket.socket()
client.connect(("127.0.0.1",8080))

while True:
    cmd=input(">>: ")
    if not cmd:continue
    client.send(bytes(cmd,encoding=‘utf-8‘))

    head=client.recv(4)
    head_json_len=struct.unpack(‘i‘,head)[0]
    head_json=json.loads(client.recv(head_json_len).decode(‘utf-8‘))
    data_len=head_json[‘data_size‘]

    recv_size=0
    recv_data=b‘‘
    while recv_size < data_len:
        recv_data = client.recv(1024) + recv_data
        recv_size = len(recv_data) + recv_size

    print(recv_data.decode(‘gbk‘))

解决粘包解决方案一 client

import socketserver
class Myserver(socketserver.BaseRequestHandler):
    def handle(self):
        self.data = self.request.recv(1024).strip()
        print("{} wrote:".format(self.client_address[0]))
        print(self.data)
        self.request.sendall(self.data.upper())

if __name__ == "__main__":
    HOST, PORT = "127.0.0.1", 9999

    # 设置allow_reuse_address允许服务器重用地址
    socketserver.TCPServer.allow_reuse_address = True
    # 创建一个server, 将服务地址绑定到127.0.0.1:9999
    #server = socketserver.TCPServer((HOST, PORT),Myserver)
    server = socketserver.ThreadingTCPServer((HOST, PORT),Myserver)
    # 让server永远运行下去,除非强制停止程序
    server.serve_forever()

tcp_server_sockserver

import socket

HOST, PORT = "127.0.0.1", 9999
data = "hello"

# 创建一个socket链接,SOCK_STREAM代表使用TCP协议
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
    sock.connect((HOST, PORT))          # 链接到客户端
    sock.sendall(bytes(data + "\n", "utf-8")) # 向服务端发送数据
    received = str(sock.recv(1024), "utf-8")# 从服务端接收数据

print("Sent:     {}".format(data))
print("Received: {}".format(received))

tcp_client_socketserver

 

原文地址:https://www.cnblogs.com/konghui/p/9900738.html

时间: 2024-10-10 08:15:33

网络编程知识点剖析的相关文章

Java网络编程知识点(1)

如何将一个String对象转换成InputStream对象? ByteArrayInputStream inputStream = new ByteArrayInputStream(str.getBytes()); 如何替换掉网络URL里面的参数值? String baseURL = "http://sixweather.3gpk.net/SixWeather.aspx?city=%s"; String cityName = "武汉"; String resultU

网络编程知识点(一)

C/S架构:客户端与服务端架构B/S架构:浏览器与服务端架构 想要实现通信,要具备网卡网线,网卡上有全球唯一mac地址多台机器实现通讯要用到交换机,一台机器通过交换机寻找一台机器叫做广播,回复的过程叫做单播arp协议:通过ip地址获取mac地址, 一台机器通过交换机要找另一台机器,然后那台机器就把自己的mac地址通过交换机回复给他 这台机器就把他的mac地址短暂缓存起来,短暂的这一段时间再想和那台机器实现通讯就不需要再广播了 机器与机器之间通过交换机连接起来形成局域网,局域网与局域网之间通过路由

Linux网络编程知识点

1.  使用read函数返回长度0的情景:对端关闭连接,服务端调用了Close函数. //intro/daytimetcpcli.c while ((n = read(sockfd, recvline, MAXLINE)) > 0){ recvline[n] = 0; if (fputs(recvline, stdout) == EOF) err_sys("fputs error"); } if (n < 0) err_sys("read error")

Socket网络编程知识点

静态方法    与类无关,不能访问类里的任何属性和方法类方法    只能访问类变量属性@property    把一个方法变成一个静态属性,    flight.status    @status.setter    flight.status = 3    @status.delter反射    getattr(obj,str)    setattr(obj,str,val)    hasattr(obj,str)    delattr(obj,str) __new__class Foo(ob

python网络编程socket (一)

提起网络编程,不同于web编程,它主要是C/S架构,也就是服务器.客户端结构的.对于初学者而言,最需要理解的不是网络的概念,而是python对于网络编程都提供了些什么模块和功能.不同于计算机发展的初级阶段,程序员走到今天,已经脱离了手工打造一切,要自己实现所有细节的年代.现在提倡的是不要重复造轮子,而是学习别人的轮子怎么用,只有那些有需求或能专研的人才去设计轮子甚至汽车,so,这是一个速成的年代. 因此,对于一个面向工作的python程序员,学习python的网络编程,其实学的就是那么几个模块,

Android网络编程系列 一 TCP/IP协议族

在学习和使用Android网路编程时,我们接触的仅仅是上层协议和接口如Apache的httpclient或者Android自带的httpURlconnection等等.对于这些接口的底层实现我们也有必要进一步的了解,这就要我们了解网络通信层了,提到网络通信层不得不说起ISO-OSI的七层协议经典架构,如图所示: 上图的左边部分就是osi架构模型了, ISO/OSI模型,即开放式通信系统互联参考模型(Open System Interconnection Reference Model),是国际标

【UNIX网络编程】进程间通信之管道

管道是最早的Unix进程间通信形式,它存在于全部的Unix实现中.关于管道,有例如以下几点须要知道: 1.它是半双工的,即数据仅仅能在一个方向上流动.虽然在某些Unix实现中管道能够是全双工的.但须要对系统进行某些设置.在Linux系统中,它是半双工的. 2.它没有名字.因此仅仅能在具有公共祖先的进程之间使用. 通经常使用在父子进程间.虽然这一点随着"有名管道FIFO"的增加得到改正了.但应该把它们看作是两种不同的进程间通信方式. 3.它由pipe函数创建,read和write函数訪问

网络版shell之网络编程练习篇--telnet服务端

网络版shell之网络编程练习篇--telnet服务端 以前写过一个shell命令解释器,对与shell命令解释器的执行流程有了清晰的认识,这段时间学习网络编程,至于网络编程的细节以及知识点,已经在上 一遍博客中,转载了从网上摘的文章,基本概括了网络编程的主要api,而对于程序员,更重要的是解决实际问题的能力,所以练习是非常重要的,现在,我们在 一起shell命令解释器的基础上,写一个基于socket网络编程的网络版shell命令解释器,也可以称之为telnet服务端.  telnet服务端代码

网络编程——The C10K Problem(C10K = connection 10 kilo 问题)。k 表示 kilo,即 1000

The C10K problem翻译 (C10K = connection 10 kilo 问题).k 表示 kilo,即 1000 比如:kilometer(千米), kilogram(千克). 如今的web服务器需要同时处理一万个以上的客户端了,难道不是吗?毕竟如今的网络是个big place了. 现在的计算机也很强大了,你只需要花大概$1200就可以买一个1000MHz的处理器,2G的内存, 1000Mbit/sec的网卡的机器.让我们来看看--20000个客户,每个为50KHz,100K