TCP/IP协议学习笔记(二)

工程建立:

    先建Project然后添加module和package,如图所示:

代码编写: 

   首先代码中会出现中文字符,所以要在代码中添加#coding utf-8,避免出现乱码。

 

   然后明确TCP/IP协议需要哪些类与方法:

                                                                     baseserver--->tcpserver-->threadingmixserver

   按照顺序进行编写:

          TCPServer 继承于 TheadingTCPServer类,按住ctrl阅读TheadingTPServer这个类 :

      发现TheadingTCPServer继承于ThreadingMixIn和TCPServer,同样按住ctrl点击TCPServer进行阅读,里面有具体的实现,初始化的方法。

 

       然后,定义一个类,继承于socketserver里的一个类StreamRequestHandler点鼠标右键里面有一个重载方法Override实现setup就可以了。


 

    最后,写测试代码判断是否能够流畅运行:

    使用元祖来规定输出的格式,address是一个元祖用括弧括起来的。实现Tserver,接收address,使用我们定义的ClientRequestHandler进行处理,修改间隔时间,点击运行。

 

运行TCP/IP代码: 

    在eclipse里点击Run as,按win+R进入命令行模式,输入telnet 192.168.1.2,远程登录,完成实验

学习反思: 

     学习中遇到的问题:

      1.输入端口号错误,导致套接字重复报错,经过查询,23号端口为Telnet端口,修改代码。

      2.重载是什么?

         答:重载就是方法名相同,参数(个数或类型)不同(称之为签名不同)

        比如:
        string test()
        {
        Console.WriteLine("Hello world");
        }  
        string test(string msg)
       {
        Console.WriteLine(msg);
       }

      这样就达到了,用同样的方法名,通过传递不同的参数,实现不同的目的 。

     3.继承怎么使用?

         答:继承是指一个对象直接使用另一对象的属性和方法。事实上,我们遇到的很多实体都有继承的含义。例如,若把汽车看成一个实体,它可以分成多个子实体,如:卡车、公共汽车等。这些子实体都具有汽车的特性,因此,汽车是它们的"父亲",而这些子实体则是汽车的"孩子"。如果一个类A继承自另一个类B,就把这个A称为"B的子类",而把B称为"A的父类"。继承可以使得子类具有父类的各种属性和方法,而不需要再次编写相同的代码。在令子类继承父类的同时,可以重新定义某些属性,并重写某些方法,即覆盖父类的原有属性和方法,使其获得与父类不同的功能。

关于服务器端的完善和客户端的编写:

         在之前的服务器端里只是重载了setup方法并没有对数据的处理,为了完善服务器端的功能将重载方法改为handle进行处理。然后定义一个清单,便于用户连接,当用户连接,进入循环获取他们的套接字,也就是他们的IP地址和端口号。并且通过self.wfile.write给客户端返回一个字符串,如果客户端向服务器端发送121的请求,通过self.rfile.read来获取并显示已获取。


'''
Created on 2018年9月25日

@author: 15006
'''
from socketserver import ThreadingTCPServer, StreamRequestHandler
from multiprocessing.connection import Client
class TServer(ThreadingTCPServer):
    def __init__(self,server_add,ClientRequestHandler):
        ThreadingTCPServer.__init__(self, server_add, ClientRequestHandler)


    
class ClientRequestHandler(StreamRequestHandler):



    def handle(self):
        Clientlist= []
        flag = True
        while flag:
            clientadd =self.client_address
            if clientadd in Clientlist:
                pass
            else:
                Clientlist.append(clientadd)
                self.wfile.write(b"hello")
                print(str(clientadd)+"已连接")
            if self.rfile.read(121):
                print(str(clientadd)+"已获取")
                pass

                
if __name__ == '__main__':
    address = ('',20025)
    server = TServer(address,ClientRequestHandler)
    server.serve_forever()
    pass

客户端的编写:

      通过ADDR来规定套接字的元祖格式,通过connect的方法进行客户端的连接。在<<<<<<<<<<输入发送给服务器端的请求,最后使用close来关闭通信。

#coding:utf-8
'''
@author: 15006
'''

from _socket import socket
from socket import *
from test.test_gzip import data1
from time import sleep

HOST='localhost'
PORT = 20025
BUFSIZ = 1024
ADDR = (HOST,PORT)

tcpCliSock = socket(AF_INET,SOCK_STREAM)
tcpCliSock.connect(ADDR)          

while True:
    data = input('>>>>>>>>> ')
    if not data:
        break
    tcpCliSock.sendall(data.encode())
    data = tcpCliSock.recv(BUFSIZ)
    if not data:
        break
    print(data)
    sleep(20)
    tcpCliSock.close()




if __name__ == '__main__':
    pass 

代码效果:

   依次运行服务器端文件和客户端文件:

  显示IP与登录端口

  在客户端输入121,收到回复hello,但是由于使用的是date.encode(),返回的是二进制流,所以显示的为b’hello’

最后服务器端读到121,显示已获得,完成一次完整的通信。

存在的问题:

1.客户端与服务器端只能建立一次通信

2.想要在代码中输入自定义的端口号,可是参考网上教程,需要编写解码器完成,多次尝试,没有成功

3.对于多线程与单线程的不太理解

4.不清楚这个代码中每次运行它显示的端口号都在改变,明明已经被定义在全局变量里了,为什么还会改变

编写过程中已经解决的问题:

1.服务器积极拒绝

   原因是没有先开启服务器端,直接运行了客户端。

2.二进制流问题

由于使用的是date.encode(),返回的是二进制流,显示的为b’hello’,将date.encode()替换为data.encode(encoding='utf_8', errors='strict')即可解决

3.为什么服务器端重载方法为handle而不是setup

因为setup只能初始化,并不能对数据进行处理,handle中可以使用wfile和rfile来处理数据。

4.客户端一直尝试与服务器进行连接,可能导致服务器端崩溃

方法一:用sleep()设置间隔时间,简单但是面对大量数据请求会造成严重卡顿现象

方法二:每次请求过后close通信通道

基本流程梳理:

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值