章节号 | 内容 |
---|---|
1图片格式(png) | 宽度大于620px,保持高宽比减低为620px |
12 | 123 |
1-1-1 | 方法 |
1-1-1 | 方法 |
第1章节 网路初步
-
1-1 网路初步—tcp ip协议(族)
4层次:链路层、网络层、传输层、应用层
7层次:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层
-
1-2 端口
就是用来区分不同的进程。范围从0-65535。
知名端口:大家都知道的端口。范围:0-1023
动态端口:动态分配的端口。范围:1024-65535
查看端口:netstat -an
li@li-ThinkPad-T420s:~$ netstat -an
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:139 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:445 0.0.0.0:* LISTEN
tcp 0 0 192.168.0.119:53582 182.242.213.227:443 ESTABLISHED
tcp 0 0 192.168.0.119:42430 180.101.136.110:443 ESTABLISHED
tcp 0 0 192.168.0.119:51912 182.131.6.245:443 ESTABLISHED
tcp 0 0 192.168.0.119:53408 52.37.42.64:443 ESTABLISHED
tcp6 0 0 :::139 :::* LISTEN
tcp6 0 0 ::1:631 :::* LISTEN
tcp6 0 0 :::445 :::* LISTEN
udp 0 0 127.0.0.53:53 0.0.0.0:*
udp 0 0 0.0.0.0:68 0.0.0.0:*
udp 0 0 192.168.0.255:137 0.0.0.0:*
udp 0 0 192.168.0.119:137 0.0.0.0:*
udp 0 0 0.0.0.0:137 0.0.0.0:*
udp 0 0 192.168.0.255:138 0.0.0.0:*
udp 0 0 192.168.0.119:138 0.0.0.0:*
udp 0 0 0.0.0.0:138 0.0.0.0:*
udp 0 0 0.0.0.0:51687 0.0.0.0:*
udp 0 0 0.0.0.0:631 0.0.0.0:*
udp 0 0 0.0.0.0:5353 0.0.0.0:*
udp6 0 0 :::55239 :::*
udp6 0 0 :::5353 :::*
raw6 0 0 :::58 :::* 7
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags Type State I-Node Path
unix 2 [ ] DGRAM 36076 /run/user/1000/systemd/notify
unix 2 [ ] DGRAM 24517 /run/user/120/systemd/notify
unix 2 [ ACC ] SEQPACKET LISTENING 16396 /run/udev/control
unix 2 [ ACC ] STREAM LISTENING 39171 /tmp/sogou-qimpanelli
unix 2 [ ACC ] STREAM LISTENING 36185 /tmp/ssh-nNqqPOVeFdvP/agent.3540
unix 2 [ ACC ] STREAM LISTENING 36079 /run/user/1000/systemd/private
unix 2 [ ACC ] STREAM LISTENING 24520 /run/user/120/systemd/private
unix 2 [ ACC ] STREAM LISTENING 36083 /run/user/1000/gnupg/S.gpg-agent.ssh
unix 2 [ ACC ] STREAM LISTENING 23412 /run/user/120/gnupg/S.gpg-agent.browser
unix 2 [ ACC ] STREAM LISTENING 36084 /run/user/1000/gnupg/S.gpg-agent.browser
unix 2 [ ACC ] STREAM LISTENING 36085 /run/user/1000/gnupg/S.gpg-agent.extra
unix 2 [ ACC ] STREAM LISTENING 23413 /run/user/120/pulse/native
unix 2 [ ACC ] STREAM LISTENING 36086 /run/user/1000/gnupg/S.dirmngr
unix 2 [ ACC ] STREAM LISTENING 23414 /run/user/120/bus
unix 2 [ ACC ] STREAM LISTENING 36087 /run/user/1000/bus
unix 2 [ ACC ] STREAM LISTENING 23415 /run/user/120/gnupg/S.gpg-agent.extra
unix 2 [ ACC ] STREAM LISTENING 36088 /run/user/1000/gnupg/S.gpg-agent
unix 2 [ ACC ] STREAM LISTENING 23416 /run/user/120/gnupg/S.dirmngr
unix 2 [ ] DGRAM 28191 /var/lib/samba/private/msg.sock/1031
unix 2 [ ACC ] STREAM LISTENING 23417 /run/user/120/gnupg/S.gpg-agent.ssh
.
.
.
端口的用处:一个ip地址可以提供多种服务,使用端口来区分不同的服务功能。如80的http,21的ftp。
为什么不用pid?多台电脑中,pid相同的程序,可能并不是同一种类的程序。
-
1-3 ip地址
作用:在逻辑上唯一的标记一台电脑。
c类地址 192. 168. 1. 1
二进制表现:1100000.10101000.00000001.00000001
私有ip:10.0.0.0-10.255.255.255
172.16.0.0-172.31.255.255
192.168.0.0-192.168.255.255
-
1-4 socket的简介(要用2台电脑测试)
本地进程间通信(IPC),如果在同一台电脑上,可以使用队列、同步等。
网络间进程的通信,使用socket套接字。
ip区分电脑,端口确定程序,协议确定通信细节,三确定就可以通信。
In [1]: import socket
In [3]: ?socket.socket()
Init signature: socket.socket(family=, type=, proto=0, fileno=None)
Docstring: A subclass of _socket.socket adding the makefile() method.
File: /usr/lib/python3.6/socket.py
Type: type
In [4]: help(socket.socket)
Help on class socket in module socket:
class socket(_socket.socket)
| A subclass of _socket.socket adding the makefile() method.
|
| Method resolution order:
| socket
| _socket.socket
| builtins.object
|
| Methods defined here:
|
| __enter__(self)
|
| __exit__(self, *args)
|
| __getstate__(self)
|
| __init__(self, family=, type=, proto=0, fileno=None)
| Initialize self. See help(type(self)) for accurate signature.
.
.
.
下面进行简单的sockte代码演示,使用udp协议发送。
import socket
#创建UDP套接字
us=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
#设置接收方的ip和端口号
addr=("192.168.0.108",8080)
#python3注意这里要加上一个字母`b`,否则产生下面的报错
data=b"hello socket"
#发送!!!!!
us.sendto(data,addr)
#关闭
us.close()
Exception has occurred: TypeError
a bytes-like object is required, not 'str'
File "/home/li/Desktop/py/ceshi.py", line 5, in
us.sendto(data,addr)
在接收方我们使用一个软件“网络调试助手”来辅助完成。按照图示设置完毕后,发送方直接运行程序,即可接收到信息如图示。
-
1-5 端口的问题、绑定端口
地址、端口,协议,三者缺一不可。
UDP类比于写信。有个地址就可以邮寄出去。每封信都有地址。
TCP类比于打电话。要先建立通路。才开始讲话。
import socket
us=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
addr=("192.168.0.108",8080)
data=b"hello socket"
us.sendto(data,addr)
us.sendto(data,addr)
us.sendto(data,addr)
us.close()
代码如上图,我们连续运行四次这段代码,看接收端的情况:
【Receive from 192.168.0.119 : 46425】:hello sockethello sockethello socket
【Receive from 192.168.0.119 : 52666】:hello sockethello sockethello socket
【Receive from 192.168.0.119 : 33521】:hello sockethello sockethello socket
【Receive from 192.168.0.119 : 34876】:hello sockethello sockethello socket
可以看到每次发送的端口都是不一样的。
PS:在同一个OS中,如果一个端口被占用了,那么其他的程序就不能再使用。很可能这个程序就要出错。
如何让自己的端口不是随机呢?那就要用到端口绑定!
import socket
us=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
addr=("192.168.0.108",8080)
#这里是关键
#如果不写ip,就表示本机的任何一个ip。baddr=("",7787)
baddr=("192.168.0.119",7787)
data=b"hello socket"
#这里是关键
us.bind(baddr)
us.sendto(data,addr)
us.sendto(data,addr)
us.sendto(data,addr)
us.close()
【Receive from 192.168.0.119 : 7787】:hello sockethello
一般来说,发送方不绑定。
接收方要绑定,为服务方。
下面编写一个接收数据的小程序:
import socket
us=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
baddr=("",7787)
us.bind(baddr)
data=us.recvfrom(1024)
print(data)
us.close()
运行后程序会阻塞住,等待接收数据。
如上图在另一端发送数据“123”,程序将自动解除阻塞并打印接收到的数据。
(b'123', ('192.168.0.108', 8080))
-
1-6 python3的编码问题及解决
import socket
us=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
addr=("192.168.0.108",8080)
#这里是关键
#如果不写ip,就表示本机的任何一个ip。baddr=("",7787)
baddr=("192.168.0.119",7787)
data=bytes("我的".encode("utf-8"))
#这里是关键
# us.bind(baddr)
us.sendto(data,addr)
us.sendto(data,addr)
us.sendto(data,addr)
us.close()
data=bytes("123aaa".encode("utf-8"))
这里使用了encode()编码功能把字符串进行了utf-8的编码,接收方在接收汉字的时候呈现了乱码(倒数第二和第三行),那么如何解决这个问题呢?
data=bytes("我的".encode("gb2312"))
【Receive from 192.168.0.119 : 38276】:我的我的我的
↑这里得到一个思考,那就是如果你发送的数据对方接收到了是乱码,则一定要考虑字符编码的一致性问题。
# 对str进行解码操作,使用gb2312的方式来解码
str.decode("gb2312"))
↓下面看一下元组的解包操作。
In [1]: a=(1111,2222)
In [2]: a
Out[2]: (1111, 2222)
In [3]: b,c=a
In [4]: b
Out[4]: 1111
In [5]: c
Out[5]: 2222
中文网站的数据,要么是utf-8,要么是gb2312
-
1-7 网络通信大体过程
-
1-8 简单的聊天室
import socket
us=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
baddr=("",7788)
us.bind(baddr)
while True:
data=us.recvfrom(1024)
print(data)
↑不停的接收数据,只要收到就打印出来。
li@li-ThinkPad-T420s:~/Desktop/py$ cd /home/li/Desktop/py ; env PYTHONIOENCODING=UTF-8 PYTHONUNBUFFERED=1 /usr/bin/python3 /home/li/.vscode/extensions/ms-python.python-2019.8.30787/pythonFiles/ptvsd_launcher.py --default --client --host localhost --port 42633 /home/li/Desktop/py/ceshi=======.py
(b'1234', ('192.168.0.108', 8081))
(b'1234', ('192.168.0.108', 8081))
(b'1234', ('192.168.0.108', 8081))
(b'1234', ('192.168.0.108', 8081))
(b'1234', ('192.168.0.108', 8081))
(b'1234', ('192.168.0.108', 8081))
Terminated
发送方使用网络调试助手即可。
-
1-9 echo服务器
接收到数据后,给予适当的反馈
import socket
us=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
baddr=("",7788)
us.bind(baddr)
while True:
data=us.recvfrom(1024)
print(data)
#关键在此句
us.sendto(b"echo",data[1])
【2019-08-27 08:23:37:985】echo
【2019-08-27 08:23:38:720】echo
【2019-08-27 08:23:39:736】echo
【2019-08-27 08:23:40:329】echo
【2019-08-27 08:23:41:364】echo
【2019-08-27 08:23:42:395】echo
【2019-08-27 08:23:43:427】echo
↑网络调试助手收到的反馈。
-
1-10 多线程模拟聊天程序
↑含服务器的聊天软件的大致过程
import socket
import threading
from threading import Thread
addr=()
def rec():
while True:
global addr
data=us.recvfrom(1024)
if addr== ():
addr=data[1]
print("\r>>"+ str(data[0].decode("gb2312")))
print(">>"+ str(data[1]))
def sed():
while True:
d=input("\r<<1").encode("gb2312")
sdata=bytes(d)
if addr== ():
print("waiting for some one")
else:
us.sendto(sdata,addr)
us=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
baddr=("",7788)
us.bind(baddr)
t1=Thread(target=rec)
t2=Thread(target=sed)
t1.start()
t2.start()
t1.join()
t2.join()
li@li-ThinkPad-T420s:~/Desktop/py$ cd /home/li/Desktop/py ; env PYTHONIOENCODING=UTF-8 PYTHONUNBUFFERED=1 /usr/bin/python3 /home/li/.vscode/extensions/ms-python.python-2019.8.30787/pythonFiles/ptvsd_launcher.py --default --client --host localhost --port 40533 /home/li/Desktop/py/ceshi.py
<<14234234
waiting for some one
<<1234234
waiting for some one
>>1234
>>('192.168.0.108', 8081)
>>1234412341234
>>('192.168.0.108', 8081)
fasfsa
<<1asfsafd
<<1asdfasfd
<<1afdasfd
<<1Terminated
【2019-08-27 08:30:58:590】fasfsa
【2019-08-27 08:30:59:402】asfsafd
【2019-08-27 08:31:00:175】asdfasfd
↑聊天的多线程实现,一个线程等待接收,一个线程等待输入,不会造成整个程序的阻塞。python端先等待对方发送信息,接收到对方的ip和端口信息后再发送。
-
1-11 wireshark
↑安装一定要勾选此选项。
-
1-12 tftp分析
首先下载tftp
打开后,点击Browse,选定一个文件路径,作为下载支持路径。此刻下载服务器已经搭建好。
下面我们开始编写一个下载器。首先:
思考如下问题:什么叫下载,它的过程是什么?
创建空文件,写数据,关闭。相当于接收。
程序概念:
f=open("文件名","bw")
while True:
rec=udpsocket.recvfrom(1024)
if xxx:
没有数据
break
else:
f.write(rec)
思考如下问题:什么叫上传?相当于发送。
程序概念:
us.sendto(sdata,addr)
那么如何与服务器端进行连接呢?换句话来说,协议是什么呢?
RFC 1350 - The TFTP Protocol (Revision 2)
RFC 959 - File Transfer Protocol
本例用的程序默认服务端口为69
1、客户端按照
读写请求
的格式,向服务器发送请求。
2、服务器向客户端发送
数据包
格式的数据。数据包最大516字节,一旦数据包小于516字节,代表整个文件传输完毕。如果是操作码3,则表示数据正确,你要回复信息,格式为ACK
。
如果文件不存在,服务器返回
ERROR
格式的错误信息。收到这个,不需要回复。
3、服务器给你发送信息,是随机端口。==69==只接收下载请求,确认包全部发往==随机端口==。
如何再windows下查看端口??使用cmd
C:>>netstat -ano | findstr 69
UDP 0.0.0.0:69 *:* 8720
找到69对应的进程id(假如为8720)。
C:>>tasklist | findstr 8720
tftp64.exe 8720 Console 1 30,764 K
现在已经确定端口号无误,可以开始了。
前置知识:struct模块的.pack()方法
。
前置知识:大端和小端。大端:是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中。
在网络上,数据都要以大端发送。
reqtext=struck.pack("!H8sb5sb",1,"test.jpg",0,"octet",0)
!表示大端顺序
H表示占2 字节
s表示占1个字节,8s表示8字节。等效于ssssssss。"test.jpg"共8个字符。
b表示1字节。
5s同上。
In [1]: import struct
In [2]: struct.pack
Out[2]:
In [3]: ?struct.pack
Docstring:
pack(fmt, v1, v2, ...) -> bytes
Return a bytes object containing the values v1, v2, ... packed according
to the format string fmt. See help(struct) for more on format strings.
Type: builtin_function_or_method
现在直接发送请求报文,看服务器端的反应。
import socket
import struct
reqtext=struct.pack("!H8sb5sb",1,b"1234.png",0,b"octet",0)
udps=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
server=("192.168.0.108",69)
udps.sendto(reqtext,server)
↑可以看到服务器端已经收到了报文的请求,但是一会就消失了,这是因为我们没有后续的应答导致。本来这里需要抓包分析,突然发现wireshark失灵。
↑原本使用正常的,突然系统自己进行了升级,出现了好多问题,win10真是一定要关闭掉破烂升级功能。
后续几番搜索解决都没有用,包括右键cmd管理员运行,均提示无效。
net start npf
最后无奈把wireshark及所有配属包全部卸载掉,然后重装,重启。
↑抓包。使用
udp port == 69
来过滤包,具体数据如上图。这里已经看到,请求报文已经发出去了,编程实现和预想是符合的。但是为什么只有一个包呢?因为限制了端口,所以其他包都被屏蔽了。下面要换一个过滤方式,来看服务器的回应是什么。
↑使用tftp
来过滤。这里一共看到了3个包。其中:
1、是我们发送的请求包。
2、是服务器返回的一个数据包。数据块号为1。
3、服务器发送的一个错误包。
import socket
import struct
g_blknum = 0
g_rf = None
reqtext = struct.pack("!H14sb5sb", 1, b"ipython.tar.gz", 0, b"octet", 0)
print(reqtext)
udps = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server = ("192.168.0.108", 69)
udps.sendto(reqtext, server)
while True:
data = udps.recvfrom(1024)
# print(len(data[0]))
# print(data[0])
# data是个元组,服务器返回的数据和服务器ip及端口
# 把纯数据部分存入rdata
rdata = data[0]
# 把端口号存入serverport
serverport = data[1][1]
# print(rdata)
# print(serverport)
# 把返回数据的操作码和块号存入opblk,再拆包
opblk = struct.unpack("!HH", rdata[0:4])
opcode, block = opblk
# print(opcode)
# print(block)
if opcode == 3:
if block == 1:
g_rf = open("ipython.tar.gz", "wb")
g_rf.write(rdata[4:])
g_blknum += 1
ackt=struct.pack("!HH", 4, block)
print(ackt)
udps.sendto(ackt, ("192.168.0.108",serverport))
if (g_blknum+1) == block:
if len(data[0]) == 516:
g_rf.write(rdata[4:])
g_blknum += 1
ackt=struct.pack("!HH", 4, block)
# print(ackt)
udps.sendto(ackt, ("192.168.0.108",serverport))
else:
g_rf.write(rdata[4:])
ackt=struct.pack("!HH", 4, block)
udps.sendto(ackt, ("192.168.0.108",serverport))
g_rf.close()
break
print(g_blknum)
↑上例是个简单的下载程序,但是在测试过程中,通过抓包发现还是会有服务器发送数据后,下载程序没有回复导致出错中止的问题。
import socket
import struct
# 全局变量计算包的数目
g_blknum = 0
# 全局变量保存文件对象
g_rf = None
# 创建一个请求报文字段
reqtext = struct.pack("!H14sb5sb", 1, b"ipython.tar.gz", 0, b"octet", 0)
print(reqtext)
# 创建UDP套接字
udps = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 构建服务器的数据元组,包含ip和端口
server = ("192.168.0.108", 69)
# 发送报文请求
udps.sendto(reqtext, server)
while True:
# 接收服务器端返回的数据
data = udps.recvfrom(1024)
# print(len(data[0]))
# print(data[0])
# data是个元组,服务器返回的数据和服务器ip及端口
# 把纯数据部分存入rdata
rdata = data[0]
# 把端口号存入serverport
serverport = data[1][1]
# print(rdata)
# print(serverport)
# 把返回数据的操作码和块号存入opblk,再拆包
opblk = struct.unpack("!HH", rdata[0:4])
opcode, block = opblk
# print(opcode)
print("reveive:")
print(block)
# 如果是数据包,则开始处理
if opcode == 3:
print("ipcode3")
# 如果是第一块,则要创建文件,并写入
if block == 1:
print("block 1")
g_rf = open("ipython.tar.gz", "wb")
g_rf.write(rdata[4:])
g_blknum += 1
ackt = struct.pack("!HH", 4, block)
print(ackt)
udps.sendto(ackt, ("192.168.0.108", serverport))
# 后续块,判断顺序是否是预期希望的,是则继续写入
if (g_blknum+1) == block:
# print("block %d" % block)
if len(data[0]) == 516:
g_rf.write(rdata[4:])
g_blknum += 1
ackt = struct.pack("!HH", 4, block)
print(ackt)
print("ackbolk"+str(block))
udps.sendto(ackt, ("192.168.0.108", serverport))
else:
#如果不是516字节,则是最后一个数据包,写完就关闭
g_rf.write(rdata[4:])
ackt = struct.pack("!HH", 4, block)
udps.sendto(ackt, ("192.168.0.108", serverport))
g_rf.close()
print("Down load Success!")
break
#差错控制,如果发来的数据块是上次接收过的,那么直接确认数据包,不再写入
elif g_blknum == block:
ackt = struct.pack("!HH", 4, block)
udps.sendto(ackt, ("192.168.0.108", serverport))
else:
print("g_blknum="+str(g_blknum))
print("block="+str(block))
if opcode == 5:
print("Down load fialed")
break
print(g_blknum)
↑附加了差错控制,貌似没有再发生中途出错问题。
-
1-13 UDP广播
udp有一种应用叫做广播。
li@li-System-Product-Name:~$ ifconfig
enp40s0: flags=4163 mtu 1500
inet 192.168.1.113 netmask 255.255.255.0 broadcast 192.168.1.255
inet6 fe80::b8d4:4d8d:b4bd:3b4d prefixlen 64 scopeid 0x20
ether 88:d7:f6:c7:41:25 txqueuelen 1000 (Ethernet)
RX packets 24616 bytes 27148422 (27.1 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 19719 bytes 2421643 (2.4 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73 mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10
loop txqueuelen 1000 (Local Loopback)
RX packets 1871 bytes 230274 (230.2 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1871 bytes 230274 (230.2 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
首先查看linux的ip地址,为下步抓取数据用。
ip.addr==192.168.0.1 //过滤ip地址
data.len==8 //过滤data部分长度为8的数据包
data.data == 00:08:30:03:00:00:00:00 //过滤指定内容的数据包
udp.srcport == 10092 //过滤经过本机10092端口的udp数据包
udp.dstport == 80 //过滤目标机器10092端口的udp数据包
udp.port==10092 //过滤本机或目标机器10092端口的数据包
udp.length == 20 //过滤指定长度的
wireshark的过滤规则
import socket
import sys
dest=("",7788)
s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
#设置套接字以发送广播
s.setsockopt(socket.SOL_SOCKET,socket.SO_BROADCAST,1)
s.sendto(b"hi",dest)
↑可以看到广播成功发送
-
1-14 tcp服务器代码编写服务器
In [1]: import socket
...:
...:
...: sTCP=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
...:
In [2]: ?sTCP.accept
Signature: sTCP.accept()
Docstring:
accept() -> (socket object, address info)
Wait for an incoming connection. Return a new socket
representing the connection, and the address of the client.
For IP sockets, the address info is a pair (hostaddr, port).
File: /usr/lib/python3.6/socket.py
Type: method
import socket
#创建一个tcp套接字
sTCP=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
addr=("",8899)
sTCP.bind(addr)
#最多可以同时5个
sTCP.listen(5)
调用accept(),返回一个新套接字,和一个地址元组
sockobj,addrinfo=sTCP.accept()
data=sockobj.recv(1024)
print(sockobj)
print(addrinfo)
print(data)
sockobj.close()
sTCP.close()
↑编写了一个简单的tcp服务,客户端使用网络调试助手。查看端口是否建立可以使用如下命令:
li@li-System-Product-Name:~$ netstat -an | grep 8899
↑注意这里程序打开以后,默认识别的网卡地址一定要和服务器在同一网段,出现识别错误的情况一定要禁用其他网卡,否则会连接错误。
li@li-System-Product-Name:~/Documents$ cd /home/li/Documents ; env PYTHONIOENCODING=UTF-8 PYTHONUNBUFFERED=1 /usr/bin/python3 /home/li/.vscode/extensions/ms-python.python-2019.8.30787/pythonFiles/ptvsd_launcher.py --default --client --host localhost --port 44557 /home/li/Documents/1.py
('192.168.1.140', 51387)
b'312312312312312313'
小结:
1、socket创建一个套接字
2、bind绑定ip和port
3、listen使套接字变为被动链接
4、accept等待客户端连接
5、recv/send接收发送数据
-
1-15 简单tcp客户端编写
from socket import *
cTCP=socket(AF_INET,SOCK_STREAM)
#服务器的ip和端口,这里和网络调试助手里的设置要相同。
cAddr=("192.168.0.108",8080)
#连接服务器
cTCP.connect(cAddr)
sData=b"im tcp client"
#发送中文要编码
sData1=bytes("哈哈哈哈".encode("gb2312"))
#发送不需要地址,因为已经连接好了服务器
#UDP发送数据因为没有之前的连接,所以需要每次发送填写接收方地址。
cTCP.send(sData)
cTCP.send(sData1)
rData=cTCP.recv(1024)
print(rData)
cTCP.close()
li@li-ThinkPad-T420s:~/Desktop/py$ cd /home/li/Desktop/py ; env PYTHONIOENCODING=UTF-8 PYTHONUNBUFFERED=1 /usr/bin/python3 /home/li/.vscode/extensions/ms-python.python-2019.8.30787/pythonFiles/ptvsd_launcher.py --default --client --host localhost --port 44409 /home/li/Desktop/py/ceshi.py
b'fasgdsfgsdgsdg'
使用网络调试助手测试成功
-
1-16 使用tcp写聊天程序