文章轉自我的CSDN博客鏈接在這TCP實現在不同局域網下的兩臺電腦網絡通信(Python實現)
之前,我曾做過在局域網下進行通信的東西。(主要是我發現沒有辦法把那個東西用在不同的局域網
的兩臺電腦)。心里一直想實現一個能在廣域網上能通信的東西!所以就有這個小項目!
實現思路:
通過一臺有公網IP的服務器作為中轉站。將局域網下的電腦轉給這個中轉的服務器,然后這個中轉的服務器將收到的數據轉給另外的一臺電腦就好了。
技術概念
下面的技術都是為了實現全雙工嘿嘿,而且也要保證傳輸的時候較為同步(網絡IO)
- 服務器多線程,接受的信息(分兩個線程)
- 客戶端實現多線程,接受信息的同時多線程輸入。
使用方法
- 在一個服務器(在公網上)運行服務端代碼。(這里我用的是,我在阿里云租的服務器)
- 兩個人(我這里,只實現了兩個人聊天的情況),分別在自己的電腦上運行起客戶端代碼(或者編譯好的客戶端程序(.exe格式))。
- 然后,直接就可以開始聊天了~
- 可以在任何時候輸入信息,敲回車就可以發出去了。
- 輸入空的信息就可以結束了,也就敲一個回車就好了。(如果一方結束了,但是另外一方沒結束就是發了,對方也收不到~ 類比于離線狀態發信息
測試結果
下面是一個受到一個遠端的信息情況和發一個信息的情況。其實這是一個全雙工聊天工具,只不過我這個演示有點不好,沒展示出來 hhh 而且這些都是手工build-wheel型hh很適合學習~ 哈哈哈
[Sat Mar 3 23:52:23 2018] : Hello
what?
代碼
客戶端代碼:
from socket import *
import threading
from time import ctime
def recv(sock, BUFSIZ):
try:
data = sock.recv(BUFSIZ)
except OSError:
return # find it was close, then close it
if data.decode() is '[CHAT]BEGIN':
print(data.decode())
elif data.decode() is '[CHAT]END':
sock.close()
else:
print('[%s]' % ctime(), ':', data.decode())
if __name__ == '__main__':
HOST = '服務器的公網IP地址'
POST = 21567
ADDR = (HOST, POST)
tcpCli = socket(AF_INET, SOCK_STREAM)
tcpCli.connect(ADDR)
threadrev = threading.Thread(target=recv, args=(tcpCli, 1024))
threadrev.start()
while True:
data = input()
if not data:
break
tcpCli.send(data.encode())
tcpCli.close()
服務端代碼~(運行在一個服務器上)
from socket import *
import threading
def trans(sock1, sock2, BUFSIZ):
while True:
try:
data = sock1.recv(BUFSIZ)
except OSError:
break
if not data:
sock1.close()
else:
try:
sock2.send(data)
except OSError:
sock1.close()
break
if __name__ == '__main__':
HOST = ''
POST = 21567
ADDR = (HOST, POST)
tcp = socket(AF_INET, SOCK_STREAM)
tcp.bind(ADDR)
tcp.listen(3)
Users = []
Addrs = []
Trans = []
while len(Users) != 2:
tcpCli, addr = tcp.accept()
Users.append(tcpCli)
trans1 = threading.Thread(target=trans, args=(Users[0], Users[1], 1024))
trans1.start()
while True:
try:
data = Users[1].recv(1024)
except OSError:
break
if not data:
Users[1].close()
else:
try:
Users[0].send(data)
except OSError:
Users[1].close()
break
tcp.close()