1. 程式人生 > >【TCP/IP】虛擬機器環境下,TCP協議的簡單實現以及[Errno 61] Connection refused的排障

【TCP/IP】虛擬機器環境下,TCP協議的簡單實現以及[Errno 61] Connection refused的排障

環境:

Mac:VIM8+YouCompleteMe+Python3

Parallels下CentOS7:VIM8+YouCompleteMe+Python3

目的:

 Mac為Client,CentOS7為Server.Server監聽埠,並對Client的TCP請求響應

實現:

Parallels的網路設定為共享網路

Mac的地址為10.211.55.2 CentOS7的地址為10.211.55.10,子網掩碼都為ff:ff:ff:00

Mac的指令碼:Python中定義了socket類,可以很方便的實現TCP協議。Client端只要知道Server端的IP和port,並用connect方法聯絡到伺服器就可以接受資料了。recv方法接受的實際是一個檔案/位元流物件,因此需要進行解碼。

#!/usr/bin/env python3
#coding=utf-8
import socket
import time
#建立一個socket的類,socket.AF_INET指的是IPV4,SOCK_STREAM指的是TCP協議,UDP協議對應socket_DRAM
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#連線PC伺服器的埠,引數是(IP/域名,埠)
ServerPort=('10.211.55.10',9999)
# connect_ex是connect()函式的擴充套件版本,出錯時返回出錯碼,而不是丟擲異常
s.connect_ex(ServerPort)

#接受伺服器的訊息,限制接受大小為1kb=1024b=128KB
while True:
    try:
    #接受訊息,並列印,解碼用utf-8
        print("Local:OK?")
        print(s.recv(1024).decode('utf-8'))
        time.sleep(1)
#傳送訊息,注意用二進位制的資料傳輸,因為傳送的實際是一個數據流
        data=(('Client'.encode('utf-8')))
        s.send(data)
    except:
        break
print("Connection is closed by Server")

CentOS7:伺服器端建立一個socket類,並對埠進行繫結和監聽;隨後用accept方法接受來自客戶端的connect請求,並得到IP和埠。隨後也和客戶端一樣,用recv和send方法接受和傳送資料,注意也是檔案或者資料流,是二進位制的物件。

#!/usr/bin/env python3
#coding=utf-8
import socket 
import os
import threading
import time

#定義一個接受和傳送資料的函式,5次傳送後即在伺服器端強行關閉連線。
def tcplink(sock,addr):
    print("Accept the new connection from %s:%s"%addr)
    sock.send(b"Welcome!Here is the Sever @10.211.55.10.")
    n=int(5)
    while n>0:
        data=sock.recv(1024)
        time.sleep(1)
        sock.send(('Server==>I have heard you.{:s}:{:d},{:d} talks remaining\n'.format(addr[0],addr[1],n-1)).encode('utf-8'))
        sock.send(('Server==>You said:{:s}\n'.format(data.decode('utf-8'))).encode('utf-8'))
        n-=1
    sock.close()
    print('Connection from %s is close.'%addr[0])

#建立socket類的例項,並繫結和監聽,閒置最大連線數為2.        
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind(('10.211.55.10',9999))
s.listen(2)
print('server is listening,waiting for connection......')

#建立一個新的程序來處理客戶端的請求
while True :
    sock,addr=s.accept()
    #注意accept方法得到的是一個socket類和一個埠地址的元組。用print命令很容易驗證。
    print(sock,addr)
    try:
        t=threading.Thread(target=tcplink,args=(sock,addr))
        tname=t.name
        print('Now {:s} is running for connection from {:s}'.format(tname,addr[0]))
        t.start()
    except :
        print("Server is block")

先啟動伺服器端:

root-> ./TCPserver.py 
server is listening,waiting for connection......

客戶端執行結果如下:

root-> ./TCPClient-10.211.55.10.py 
Local:OK?
Welcome!Here is the Sever @10.211.55.10.
Local:OK?
Server==>I have heard you.10.211.55.2:53387,4 talks remaining

Local:OK?
Server==>You said:Client

Local:OK?
Server==>I have heard you.10.211.55.2:53387,3 talks remaining

Local:OK?
Server==>You said:Client

Local:OK?
Server==>I have heard you.10.211.55.2:53387,2 talks remaining

Local:OK?
Server==>You said:ClientClient

Local:OK?
Server==>I have heard you.10.211.55.2:53387,1 talks remaining

Local:OK?
Server==>You said:ClientClient

Local:OK?
Server==>I have heard you.10.211.55.2:53387,0 talks remaining

Connection is closed by Server

客戶端執行完畢後,伺服器端:

root-> ./TCPserver.py 
server is listening,waiting for connection......
<socket.socket fd=4, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('10.211.55.10', 9999), raddr=('10.211.55.2', 53387)> ('10.211.55.2', 53387)
Now Thread-1 is running for connection from 10.211.55.2
Accept the new connection from 10.211.55.2:53387
Connection from 10.211.55.2 is close.

遇見的問題:

1 出現了伺服器拒絕連線的問題

   s.connect(ServerPort)
ConnectionRefusedError: [Errno 61] Connection refused

  首先ping伺服器,可以連通,說明路由沒有問題;在客戶端用curl探測埠,發現22埠正常,9999埠被拒絕。

root-> curl 10.211.55.10:22
SSH-2.0-OpenSSH_7.4
Protocol mismatch.
curl: (56) Recv failure: Connection reset by peer

root-> curl 10.211.55.10:9999
curl: (7) Failed to connect to 10.211.55.10 port 9999: Connection refused

說明可能是防火牆阻擋了TCP的請求。然後開始坑爹的CentOS防火牆設定,最終才搞定:

#關閉firewalls並禁止開機啟動
root->systemctl stop firewalld.service
root->systemctl disable firewalld.service

#安裝iptables.service,注意不是iptables命令
root->yum install iptables.service

#配置iptables,必須先安裝iptables.service,否則不能生產iptables這個檔案
root->vim /etc/sysconfig/iptables
#加上這條:
-A INPUT -p tcp -m state --state NEW -m tcp --dport 9999 -j ACCEPT
systemctl enable iptables.service
systemctl start iptables.service

#編輯selinux的選項
vim /etc/selinux/config
#註釋掉SELINUXTYPE=targeted

2 虛擬機器因為頻繁的開關,導致時鐘不同步。

在編譯或者安裝一些檔案時易出錯。

#!/usr/bin/bash
ntpdate cn.pool.ntp.org
if [ x$? = x0 ] ;then
	echo "os time is OK"	
	else 
	echo "os time is NOK"
fi
hwclock --systohc --localtime
if [ x$? = x0 ] ;then
	echo "mainboard time is OK"	
	else 
	echo "mainboard time is NOK"
fi