前言

参考了《python核心编程 第三版》的socket编程部分,采用VMware+kali+gns3的环境进行python编程

配置环境

tcp聊天程序 python python socket tcp编程_vmware


以配置服务器KALI 1为例,客户端KALI 2同理

编辑网卡eth0的ip地址

gedit /etc/network/interfaces

auto eth0
iface eth0 inet static
address 192.167.5.8
netmask 255.255.255.0
gateway 192.167.5.8

取消托管,启用静态ip

gedit /etc/NetworkManager/NetworkManager.conf

managed=true

managed=true,手工处理好了,NetworkManager将不管interfaces列出的网卡,在interfaces中的网卡生效
managed=false,没有手工处理,NetworkManager将会管理配置所有的有线/无线网卡,interfaces中的配置无效;

使网络配置生效

网上都是用桥接模式搭配

/etc/init.d/networking restart

但我用gns3连俩虚拟机,是自定义网络适配器模式
所以这句话无效,只能

改一次ip重启一次虚拟机

检验效果

ifconfig

TCP服务器和客户端连接

str型和bytes型

str型,以Unicode格式(多个字节)为单位,用于显示
bytes型,以一个字节为单位,用于传输

服务器

#!usr/bin/env python
from socket import *
from time import ctime
import sys
host = ''#服务器本身任意可用的地址
port = 21567#服务器端口
bufsiz = 1024#最大接收字节
addrport = (host,port)#地址端口对
#AF_INET基于网络,应用广泛;SOCK_STREAM基于字节流方式
tcpsersock = socket(AF_INET,SOCK_STREAM)#生成TCP服务器套接字
try:
    tcpsersock.bind(addrport)#绑定地址端口对
    tcpsersock.listen(5)#开启监听,连接数最大为5
    while True:
        print('waiting for connection...')
        tcpclisock,addr=tcpsersock.accept()#阻塞,接收到了一个客户端的句柄和地址,就交给下边的对话循环处理,然后继续监听接收,最多收5个
        print('...connected from:',addr)
        while True:
            data=tcpclisock.recv(bufsiz)#收最多1024字节消息,data是bytes型
            if not data:#空字节返回
                break
            #返回给客户端,ctime()是当前时间,str型,加个好看的[],还是str型.把str型转成bytes型,用bytes(str,'utf-8')
            k=bytes("[{}]".format(ctime()),'utf-8')+data
            tcpclisock.send(k)#send()的参数是bytes型
        tcpclisock.close()#因空字节返回的对话结束,关掉此客户端连接
except TypeError:
    sys.exit("TypeError")
except OSError:
    tcpsersock.close()
    sys.exit("oserror")
except KeyboardInterrupt:
    sys.exit("KeyboardInterrupt")
finally:
    tcpsersock.close()#关掉服务器连接

客户端

#!usr/bin/env python
from socket import *
host = '192.167.5.8'#目的服务器地址
port = 21567#目的服务器开放端口
bufsiz = 1024
addr = (host,port)#地址端口对
tcpclisock = socket(AF_INET,SOCK_STREAM)
tcpclisock.connect(addr)#绑定地址端口对连接服务器
while True:
    data = input('> ')#输入的是str型
    if not data:
        break
    tcpclisock.send(str.encode(data))#send参数是bytes型,把str型转成bytes型,还可以用str.encode(s),也可以用刚才的bytes(data,'utf-8')
    data = tcpclisock.recv(bufsiz)#返回的是bytes型
    if not data:
        break
    print(data.decode('utf-8'))#把bytes型转化成str型,用decode('utf-8')
tcpclisock.close()

成果

先开服务器

waiting for connection...
...connected from: ('192.167.5.9', 60418)
waiting for connection...

再开客户端

输入数目返回什么,还加个时间戳.直接输入回车就结束.

> hello server
[Sun Apr  8 21:28:23 2018]hello server
> i am from kali
[Sun Apr  8 21:28:37 2018]i am from kali
>

Process finished with exit code 0

总结

套接字双方套的都是服务器的ip地址和端口,传的时候用bytes型这个格式
服务器监听客户连接,来一个客户就交付给对话循环,监听仍然继续