#coding=utf-8

# socket

#网络中进程之间通信:网络层的“ip地址”可以唯一标识网络中的主机,而传输层的“协议+端口”可以唯一标识主机中的应用程序(进程)。利用ip地址,协议,端口就可以标识网络的进程了,网络中的进程通信就可以利用这个标志与其它进程进行交互

#socket(简称 套接字) 是进程间通信的一种方式,它与其他进程间通信的一个主要不同是:它能实现不同主机间的进程间通信,我们网络上各种各样的服务大多都是基于 Socket 来完成通信的;例如我们每天浏览网页、QQ 聊天、收发 email 等等

#创建socket: Python 中 使用socket 模块的函数 socket 就可以完成:socket.socket(AddressFamily, Type),函数 socket.socket 创建一个 socket,返回该 socket 的描述符,该函数带有两个参数:Address Family:可以选择 AF_INET(用于 Internet 进程间通信) 或者 AF_UNIX(用于同一台机器进程间通信),实际工作中常用AF_INET;Type:套接字类型,可以是 SOCK_STREAM(流式套接字,主要用于 TCP 协议)或者 SOCK_DGRAM(数据报套接字,主要用于 UDP 协议)

#创建一个tcp socket(tcp套接字)

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

print('Socket Created')#Socket Created

#创建一个udp socket(udp套接字)

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

print('Socket Created')#Socket Created

#创建一个udp客户端程序的流程是简单,具体步骤如下:创建客户端套接字;发送/接收数据;关闭套接字

#发送数据

#coding=utf-8

from socket import *

#1. 创建套接字

udpSocket = socket(AF_INET, SOCK_DGRAM)

#2. 准备接收方的地址

sendAddr = ('192.168.80.1', 8080)

#3. 从键盘获取数据

sendData = input("请输入要发送的数据:")

#4. 发送数据到指定的电脑上

udpSocket.sendto(sendData.encode('utf-8'), sendAddr)

#5. 关闭套接字

udpSocket.close()

#接收数据

#coding=utf-8

from socket import *

#1. 创建套接字

udpSocket = socket(AF_INET, SOCK_DGRAM)

#2. 准备接收方的地址

sendAddr = ('192.168.80.1', 8080)

#3. 从键盘获取数据

sendData = input("请输入要发送的数据:")

#4. 发送数据到指定的电脑上

udpSocket.sendto(sendData.encode('utf-8'), sendAddr)

#5. 等待接收对方发送的数据

recvData = udpSocket.recvfrom(1024) # 1024表示本次接收的最大字节数

#6. 显示对方发送的数据

print(recvData)#(b'haha1', ('192.168.80.1', 8080))

#7. 关闭套接字

udpSocket.close()

#每重新运行一次网络程序,端口不一样的原因在于,当重新运行时,如果没有确定到底用哪个,系统默认会随机分配。记住一点:这个网络程序在运行的过程中,这个就唯一标识这个程序,所以如果其他电脑上的网络程序如果想要向此程序发送数据,那么就需要向这个数字(即端口)标识的程序发送即可

#udp绑定信息

#coding=utf-8

from socket import *

#1. 创建套接字

udpSocket = socket(AF_INET, SOCK_DGRAM)

#2. 绑定本地的相关信息,如果一个网络程序不绑定,则系统会随机分配

bindAddr = ('', 7788) # ip地址和端口号,ip一般不用写,表示本机的任何一个ip

udpSocket.bind(bindAddr)

#3. 等待接收对方发送的数据

recvData = udpSocket.recvfrom(1024) # 1024表示本次接收的最大字节数

#4. 显示接收到的数据

print(recvData)#(b'thanks', ('192.168.80.1', 8080))

#5. 关闭套接字

udpSocket.close()

#一个udp网络程序,可以不绑定,此时操作系统会随机进行分配一个端口,如果重新运行次程序端口可能会发生变化,一个udp网络程序,也可以绑定信息(ip地址,端口号),如果绑定成功,那么操作系统用这个端口号来进行区别收到的网络数据是否是此进程的

#udp应用:echo服务器,echo服务端循环等待对方发数据,再发送回去

#coding=utf-8

from socket import *

#1. 创建套接字

udpSocket = socket(AF_INET, SOCK_DGRAM)

#2. 绑定本地的相关信息

bindAddr = ('', 7788) # ip地址和端口号,ip一般不用写,表示本机的任何一个ip

udpSocket.bind(bindAddr)

num = 1

while True:

#3. 等待接收对方发送的数据

recvData = udpSocket.recvfrom(1024) # 1024表示本次接收的最大字节数

#4. 将接收到的数据再发送给对方

udpSocket.sendto(recvData[0], recvData[1])

#5. 统计信息

print('已经将接收到的第%d个数据返回给对方,内容为:%s'%(num,recvData[0]))

num+=1

#5. 关闭套接字

udpSocket.close()

#udp应用:聊天室

#coding=utf-8

from socket import *

from time import ctime

#1. 创建套接字

udpSocket = socket(AF_INET, SOCK_DGRAM)

#2. 绑定本地的相关信息

bindAddr = ('', 7788) # ip地址和端口号,ip一般不用写,表示本机的任何一个ip

udpSocket.bind(bindAddr)

while True:

#3. 等待接收对方发送的数据

recvData = udpSocket.recvfrom(1024) # 1024表示本次接收的最大字节数

#4. 打印信息

print('【%s】%s:%s'%(ctime(),recvData[1][0],recvData[0]))#【Mon Nov 23 11:25:58 2020】192.168.80.1:b'thank2'

#5. 关闭套接字

udpSocket.close()

#1. udp是TCP/IP协议族中的一种协议能够完成不同机器上的程序间的数据通信;2. udp服务器、客户端:udp的服务器和客户端的区分:往往是通过请求服务和提供服务来进行区分;请求服务的一方称为:客户端;提供服务的一方称为:服务器;3. udp绑定问题:一般情况下,服务器端,需要绑定端口,目的是为了让其他的客户端能够正确发送到此进程,客户端,一般不需要绑定,而是让操作系统随机分配,这样就不会因为需要绑定的端口被占用而导致程序无法运行的情况

#TFTP(Trivial File Transfer Protocol,简单文件传输协议):是TCP/IP协议族中的一个用来在客户端与服务器之间进行简单文件传输的协议。适合在局域网进行传递,端口号为69,基于UDP实现

#TFTP服务器默认监听69号端口,当客户端发送“下载”请求(即读请求)时,需要向服务器的69端口发送,服务器若批准此请求,则使用一个新的、临时的 端口进行数据传输。当服务器找到需要现在的文件后,会立刻打开文件,把文件中的数据通过TFTP协议发送给客户端,如果文件的总大小较大(比如3M),那么服务器分多次发送,每次会从文件中读取512个字节的数据发送过来,因为发送的次数有可能会很多,所以为了让客户端对接收到的数据进行排序,所以在服务器发送那512个字节数据的时候,会多发2个字节的数据,用来存放序号,并且放在512个字节数据的前面,序号是从1开始的。因为需要从服务器上下载文件时,文件可能不存在,那么此时服务器就会发送一个错误的信息过来,为了区分服务发送的是文件内容还是错误的提示信息,所以又用了2个字节 来表示这个数据包的功能(称为操作码),并且在序号的前面。

"""

操作码                  功能

1                       读请求,即下载

2                       写请求,即上传

3                       表示数据包,即DATA

4                       确认码,即ACK

5                       错误

"""

#因为udp的数据包不安全,即发送方发送是否成功不能确定,所以TFTP协议中规定,为了让服务器知道客户端已经接收到了刚刚发送的那个数据包,所以当客户端接收到一个数据包的时候需要向服务器进行发送确认信息,即发送收到了,这样的包成为ACK(应答包)。为了标记数据已经发送完毕,所以规定,当客户端接收到的数据小于516(2字节操作码+2个字节的序号+512字节数据)时,就意味着服务器发送完毕了。

#在192.168.80.128上搭建TFTP服务器,1、yum install xinetd tftp tftp-server        # root 用户执行

# 2、配置tftp-server

"""

# [root@localhost ~]# cat /etc/xinetd.d/tftp

# default: off

# description: The tftp server serves files using the trivial file transfer \

#    protocol.  The tftp protocol is often used to boot diskless \

#    workstations, download configuration files to network-aware printers, \

#    and to start the installation process for some operating systems.

service tftp

{

socket_type        = dgram

protocol           = udp

wait               = yes

user               = root

server             = /usr/sbin/in.tftpd

server_args        = -s /var/lib/tftpboot -c   # 注意这行,如果允许上传,一定要加上参数 -c

disable            = no   # 这行默认为yes,改成no,允许

per_source         = 11

cps                = 100 2

flags              = IPv4

}

"""

#3、启动服务

"""

[root@localhost ~]#systemctl restart xinetd.service

[root@localhost ~]# netstat -a | grep tftp

udp        0      0 0.0.0.0:tftp            0.0.0.0:*

udp6       0      0 [::]:tftp               [::]:*

[root@localhost ~]# netstat -tunap | grep :69

udp        0      0 0.0.0.0:69              0.0.0.0:*                           30014/xinetd

udp6       0      0 :::69                   :::*                                1/systemd

"""

#4、如果上传时出现"连接请求失败"的提示,请确保tftp服务的文件存放目录权限设置正确

#解决办法:chmod  0777  /var/lib/tftpboot   #其中tftpboot为上传和下载文件存储目录

#coding:utf-8

from socket import *

import struct

import sys

if len(sys.argv) != 2:

print('-'*30)

print("tips:")

print("python network.py 192.168.80.128")

print('-'*30)

exit()

else:

ip = sys.argv[1]

# 创建udp套接字

udpSocket = socket(AF_INET, SOCK_DGRAM)

#构造下载请求数据

cmd_buf = struct.pack("!H8sb5sb".encode('utf-8'),1,"test.jpg".encode('utf-8'),0,"octet".encode('utf-8'),0)

#发送下载文件请求数据到指定服务器

sendAddr = ('192.168.80.128', 69)

udpSocket.sendto(cmd_buf, sendAddr)

p_num = 0

recvFile = ''

while True:

recvData,recvAddr = udpSocket.recvfrom(1024)

recvDataLen = len(recvData)

# print recvAddr # for test

# print len(recvData) # for test

cmdTuple = struct.unpack("!HH", recvData[:4])

# print cmdTuple # for test

cmd = cmdTuple[0]

currentPackNum = cmdTuple[1]

if cmd == 3: #是否为数据包

# 如果是第一次接收到数据,那么就创建文件

if currentPackNum == 1:

recvFile = open("test.jpg", "ab")

# 包编号是否和上次相等

if p_num+1 == currentPackNum:

recvFile.write(recvData[4:])

p_num +=1

print('(%d)次接收到的数据'%(p_num))

ackBuf = struct.pack("!HH",4,p_num)

udpSocket.sendto(ackBuf, recvAddr)

# 如果收到的数据小于516则认为出错

if recvDataLen<516:

recvFile.close()

print('已经成功下载!!!')

break

elif cmd == 5: #是否为错误应答

print("error num:%d"%currentPackNum)

break

udpSocket.close()

"""

PS D:\python> python network.py test.jpg

(1)次接收到的数据

(2)次接收到的数据

已经成功下载!!!

"""

#网络编程中的广播

#coding=utf-8

import socket, sys

dest = ('', 7788)

# 创建udp套接字

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 对这个需要发送广播数据的套接字进行修改设置,否则不能发送广播数据

s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST,1)

# 以广播的形式发送数据到本网络的所有电脑中

s.sendto("Hi".encode('utf-8'), dest)

print("等待对方回复(按ctrl+c退出)")

while True:

(buf, address) = s.recvfrom(2048)

print("Received from %s: %s" % (address, buf))

"""客户端(UDP协议局域网广播)"""

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)

PORT = 7788

s.bind(('', PORT))

print('Listening for broadcast at ', s.getsockname())

while True:

data, address = s.recvfrom(65535)

print('Server received from {}:{}'.format(address, data.decode('utf-8')))

#如果想要完成一个tcp服务器的功能,需要的流程如下:socket创建一个套接字;bind绑定ip和port;listen使套接字变为可以被动链接;accept等待客户端的链接;recv/send接收发送数据

#先运行这段代码作为服务端,打开客户端链接服务端,发送信息“哈哈”,客户端会收到:[2020-11-23 16:01:25.449]# RECV ASCII>thank you !

#coding=utf-8

from socket import *

# 创建socket

tcpSerSocket = socket(AF_INET, SOCK_STREAM)

# 绑定本地信息

address = ('', 7788)

tcpSerSocket.bind(address)

# 使用socket创建的套接字默认的属性是主动的,使用listen将其变为被动的,这样就可以接收别人的链接了

tcpSerSocket.listen(5)

# 如果有新的客户端来链接服务器,那么就产生一个新的套接字专门为这个客户端服务器;newSocket用来为这个客户端服务;tcpSerSocket就可以省下来专门等待其他新客户端的链接

newSocket, clientAddr = tcpSerSocket.accept()

# 接收对方发送过来的数据,最大接收1024个字节

recvData = newSocket.recv(1024)

recvData = recvData.decode('gb2312')#中文编码

print('接收到的数据为:',recvData)

# 发送一些数据到客户端

newSocket.send("thank you !".encode('utf-8'))

# 关闭为这个客户端服务的套接字,只要关闭了,就意味着为不能再为这个客户端服务了,如果还需要服务,只能再次重新连接

newSocket.close()

# 关闭监听套接字,只要这个套接字关闭了,就意味着整个程序不能再接收任何新的客户端的连接

tcpSerSocket.close()

#tcp客户端构建流程

#coding:utf-8

from socket import *

# 创建socket

tcpClientSocket = socket(AF_INET, SOCK_STREAM)

# 链接服务器

serAddr = ('192.168.80.1', 7788)

tcpClientSocket.connect(serAddr)

# 提示用户输入数据

sendData = input("请输入要发送的数据:")

tcpClientSocket.send(sendData.encode('utf-8'))

# 接收对方发送过来的数据,最大接收1024个字节

recvData = tcpClientSocket.recv(1024).decode('gb2312')

print('接收到的数据为:',recvData)

# 关闭套接字

tcpClientSocket.close()

#模拟QQ聊天

#客户端

#coding=utf-8

from socket import *

# 创建socket

tcpClientSocket = socket(AF_INET, SOCK_STREAM)

# 链接服务器

serAddr = ('192.168.80.1', 7788)

tcpClientSocket.connect(serAddr)

while True:

# 提示用户输入数据

sendData = input("send:")

if len(sendData)>0:

tcpClientSocket.send(sendData.encode('utf-8'))

else:

break

# 接收对方发送过来的数据,最大接收1024个字节

recvData = tcpClientSocket.recv(1024)

print('recv:',recvData.decode('gb2312'))

# 关闭套接字

tcpClientSocket.close()

#服务器端

#coding=utf-8

from socket import *

# 创建socket

tcpSerSocket = socket(AF_INET, SOCK_STREAM)

# 绑定本地信息

address = ('', 7788)

tcpSerSocket.bind(address)

# 使用socket创建的套接字默认的属性是主动的,使用listen将其变为被动的,这样就可以接收别人的链接了

tcpSerSocket.listen(5)

while True:

# 如果有新的客户端来链接服务器,那么就产生一个信心的套接字专门为这个客户端服务器,    # newSocket用来为这个客户端服务,    # tcpSerSocket就可以省下来专门等待其他新客户端的链接

newSocket, clientAddr = tcpSerSocket.accept()

while True:

# 接收对方发送过来的数据,最大接收1024个字节

recvData = newSocket.recv(1024).decode('gb2312')

# 如果接收的数据的长度为0,则意味着客户端关闭了链接

if len(recvData)>0:

print('recv:',recvData)

else:

break

# 发送一些数据到客户端

sendData = input("send:")

newSocket.send(sendData.encode('utf-8'))

# 关闭为这个客户端服务的套接字,只要关闭了,就意味着为不能再为这个客户端服务了,如果还需要服务,只能再次重新连接

newSocket.close()

# 关闭监听套接字,只要这个套接字关闭了,就意味着整个程序不能再接收任何新的客户端的连接

tcpSerSocket.close()

#listen的队列长度

#服务器端

#coding=utf-8

from socket import *

from time import sleep

# 创建socket

tcpSerSocket = socket(AF_INET, SOCK_STREAM)

# 绑定本地信息

address = ('', 7788)

tcpSerSocket.bind(address)

connNum = int(input("请输入要最大的链接数:"))

# 使用socket创建的套接字默认的属性是主动的,使用listen将其变为被动的,这样就可以接收别人的链接了。代表可建立socket连接的排队的个数windows,mac 此连接参数有效,Linux 此连接参数无效,默认最大

#bacuklog的定义:在进程正理一个一个连接请求的时候,可能还存在其它的连接请求。因为TCP连接是一个过程,所以可能存在一种半连接的状态,有时由于同时尝试连接的用户过多,使得服务器进程无法快速地完成连接请求。如果这个情况出现了,服务器进程希望内核如何处理呢?内核会在自己的进程空间里维护一个队列以跟踪这些完成的连接但服务器进程还没有接手处理或正在进行的连接,这样的一个队列内核不可能让其任意大,所以必须有一个大小的上限。这个backlog告诉内核使用这个数值作为上限。

#当客户端请求到来时,服务器会处理他们的请求,在你的代码中就是创建一个线程来处理。那么请求多了之后就会创建很多个线程,这样服务器资源总会到达上限。backlog为5,实际上不是限制处理的线程为5,而是当服务器忙不过来了,内核会hold住一个长度为5的队列,一旦服务器忙过来了,就会从这个队列中拿出一个来处理,直到队列为空。

tcpSerSocket.listen(connNum)

while True:

# 如果有新的客户端来链接服务器,那么就产生一个新的套接字专门为这个客户端服务器

newSocket, clientAddr = tcpSerSocket.accept()

print(clientAddr)

sleep(1)

#客户端运行

#coding=utf-8

from socket import *

connNum = input("请输入要链接服务器的次数:")

for i in range(int(connNum)):

s = socket(AF_INET, SOCK_STREAM)

s.connect(("192.168.80.1", 7788))

print(i)

#listen中的black表示已经建立链接和半链接的总数,如果当前已建立链接数和半链接数以达到设定值,那么新客户端就不会connect成功,而是等待服务器

asp.core api 通过socket和服务器通信发送udp_python socket之TCP/UDP相关推荐

  1. asp.core api 通过socket和服务器通信发送udp_读懂Java中的Socket编程

    Socket,又称为套接字,Socket是计算机网络通信的基本的技术之一.如今大多数基于网络的软件,如浏览器,即时通讯工具甚至是P2P下载都是基于Socket实现的.本文会介绍一下基于TCP/IP的S ...

  2. asp.core api 通过socket和服务器通信发送udp_详解Linux的SOCKET编程

    文章来自于 https://www.zhangshengrong.com/p/9Oabd95XdK/ PHP进阶学习交流QQ群:983229225 本篇文章对Linux的SOCKET编程进行了详细解释 ...

  3. asp.core api 通过socket和服务器通信发送udp_【网络通信】TCP的通信过程

    本文主要介绍以下几个内容: 1.TCP.UDP.Socket分别是什么?有什么区别? 2.TCP的基本过程. 3.TCP三次握手建立连接. 4.TCP四次挥手断开连接. 5.常考查其他问题. 1.TC ...

  4. android socket 代理服务器,Android 使用Socket进行服务器通信

    ·使用Socket进行简单服务器通信 简单服务器端: public class ServerThread implements Runnable{ Socket s=null; BufferedRea ...

  5. 关于java使用socket与服务器通信的总结

    socket客户端demo 1.创建springboot项目 此处省略 2. 依赖jar 添加pom.xml <?xml version="1.0" encoding=&qu ...

  6. 高性能udp服务器架构,优秀的国产高性能TCP/UDP/HTTP开源网络通信框架——HP

    介绍 HP-Socket是国人开发的一套高性能的TCP/UDP/HTTP网络通信框架,包含了服务端.客户端以及Agent组件,可用于各种不同应用场景的通信系统,并且提供了C/C++.C#.Delphi ...

  7. Linux下Socket客户端服务器通信

    Linux/Unix系统一切都是文件 Linux系统中,存在一个虚拟文件系统VFS,把一切实体视为文件,包括普通文件.音视频.输入输出设备等.这样,操作系统可以可以提供统一的接口来操作任何实体.每个& ...

  8. 基于Android硬件设备跟微信服务器通信的项目心得,以UDP Byte通信为例,建立无向连接,0530手札

    这段时间挺忙的,微信企业号等微信系列的教程全部停滞了,原因是我手头上抓着几个项目,加班就不说了,今天刚刚把新接手的项目整到大概%80的样 子吧,准备明天整整,星期一过来直接对接测试,很多朋友跑过来问问 ...

  9. Android 通过Socket 和服务器通讯

    Android 通过Socket 和服务器通讯,是一种比较常用的通讯方式,时间比较紧,说下大致的思路,希望能帮到使用socket 进行通信的人 (1)开启一个线程发送消息    SocketOutpu ...

最新文章

  1. Android开发之核心特性SearchView的开发使用(源代码分享)
  2. Ping一下Github,确认本地DNS无法解析方法
  3. Linux安装GitLib
  4. 保留3位小数的浮点数(信息学奥赛一本通-T1024)
  5. Python-面向对象(进阶)
  6. 【编程珠玑】第十一章 排序 (插入排序和快速排序的深度优化)
  7. 智能一代云平台(二十一):生产环境Nginx报 502 Bad Gateway 问题复现及解决方案
  8. 10. Javascript DOM节点
  9. 本特利前置器330180-90-00
  10. 【SysML精粹】系统建模语言概览
  11. udp简单通讯示例---心跳示例
  12. cocosCreator 骨骼动画
  13. mac 打印机设置成黑白打印
  14. 【眼镜片】绿膜和蓝膜有什么区别?
  15. 日常报错记录Could not find com.android.tools.build:gradle:3.2.1. variant: debug/0 from output dir Failure
  16. system information
  17. Portainer-docker可视化工具
  18. Arduino开发-TFT_eSPI库学习
  19. win10看视频全屏底边任务栏还在
  20. canvas 涂鸦画板,支持笔写、手写、鼠标绘图

热门文章

  1. [开发笔记]-DataGridView控件中自定义控件的使用
  2. mysql5.7中root密码忘记后修改密码
  3. 物联网产品背后潜藏着危机
  4. Linux下怎么确定Nginx安装目录
  5. React.js 2016 最佳实践 徬梓阅读 1584收藏 71
  6. PHP案例 网页计数器设计
  7. 网络分层协议图以及各层的简介
  8. SEO优化技巧:16个方法优化网页中的图片
  9. 利用PostMan 模拟上传/下载文件(亲测)
  10. LocalDateTime、LocalDate、Date的相互转换(亲测LocalDateTime转LocalDate)