学习计算机最好方式,就是动手实践,然后当你遇到问题时,再返回书本去查。废话不多说,直接来来体验下网络编程吧。
1. 目标:写一个基于TCP的C/S聊天系统
2. 拟采用的技术 Python及其网络库,多线程库
socket.
socket
(
family=AF_INET,
type=SOCK_STREAM,
proto=0,
fileno=None
)
bind()
listen()
accept()
recv()
send()
connect()
threading()
3. 思路
TCP客户端:
1). 新建socket对象
2). 连接远程服务器
3). 向远程服务器发送消息
4). 接收远程服务器返回的消息
5). 打印消息,关闭连接
TCP服务端:
1). 新建socket对象
2). 绑定IP和端口
3). 进入监听状态
4). 接收客户端的连接请求
5). 接收客户端的消息
6). 打印客户端消息
7). 向客户端返回消息
8). 关闭客户端连接
4. 接下来看下代码:
TCP客户端代码:
import socket
target_host = "192.168.31.148"
target_port = 8086
#client.send("GET / HTTP/1.1\r\nHost:www.baidu.com\r\n\r\n")
while(True):
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect((target_host,target_port))
msg = input()
client.send(msg.encode())
response = client.recv(4096)
print(response)
client.close()
TCP服务端代码:
import socket
import threading
bind_ip = '192.168.31.148'
bind_port = 8086
# create a socket server object
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# bind host ip and port
server.bind((bind_ip,bind_port))
# listen
server.listen(10)
print("[*] server listen on %s:%d"%(bind_ip,bind_port))
def handle_client(client_socket):
request = client_socket.recv(4096)
print("[*] received:%s"%(request))
ack = input()
client_socket.send(ack.encode())
client_socket.close()
while(True):
client,addr = server.accept()
print("[*] Accepted connection from %s,%d"%(addr[0],addr[1]))
client_handler = threading.Thread(target=handle_client,args=(client,))
client_handler.start()
5. 运行效果
1)先在服务端启动server
$ python3 server.py
[*] server listen on 192.168.31.148:8086
2)客户端连接服务端(由于我是在sublime中写的,所以直接在sublime中运行客户端,依次选择Tools->sublime REPL->Python->run current file)
运行客户端以后就可以发送消息了,client是客户端发给服务器的消息,server是来自服务端的消息
I am client
b'server'
I am client2
b'server2'
3)服务端的响应
[*] server listen on 192.168.31.148:8086
[*] Accepted connection from 192.168.31.182,59537
[*] received:b'I am client'
server
[*] Accepted connection from 192.168.31.182,59757
[*] received:b'I am client2'
server2
[*] Accepted connection from 192.168.31.182,60045
6. 可能遇到的问题
1)编写的过程中,曾经遇到过10053错误,原因是远程服务端已经关闭了连接,但是客户端未关闭,仍然尝试使用现有连接发送消息,也就是客户端处于所谓的半连接状态,会得到这个错误。
2)由于TCP发送每条消息都需要建立一次连接,发送消息,关闭连接,因此理论上需要3+n+4个包,三次握手,n次数据,4次挥手,很不划算,可见,可靠性的保障需要付出额外的代价来保障。
3) 结合抓包工具wireshark,会发现更多有趣的事实