• Python拾忆--多线程的socket服务器


          阳光明媚的午后,想想最近要开始从写Java到写Python了,就随手打开电脑来体验一下Python与Java之间的不同吧~

          记得我还在上大二的时候,那个时候才开始学Java,最感兴趣的就是Java书最后章节讲的socket套接字那部分,第一次看到同时打开多个黑底白字的shell界面的样子,那么的激动T.T~那个时候还不知道什么是多线程,一个客户端就让其他的客户端不工作了…..那会感觉多线程是我学的最麻烦的地方….那时用了一个下午搞了个多线程的socket程序乐呵呵的玩了好久~~

          要说我最讨厌Python什么,那一定是它没有java一个方法中的{},取而代之的居然是缩进….真心好不爽额….吐槽就到这里了T.T,这次看了一下Python的socket教程发现和Java大同小异,依旧是创建连接,客户和服务器通过send和recv方法通信,最后进行关闭,而为了防止一个客户端与服务端连接导致其他客户端挂起的现象,我还特意加上了Python的多线程来保证不会出现这个现象,对于Python的多线程,我更倾向于创建threading.Thread的子类来包装一个线程对象,可能这与我经常写Java有关吧~~更熟悉这种方式,下面就把服务端和客户端的代码贴出来:

    #coding=utf-8 
    import socket
    import threading,getopt,sys,string
    
    opts, args = getopt.getopt(sys.argv[1:], "hp:l:",["help","port=","list="])
    #设置默认的最大连接数和端口号,在没有使用命令传入参数的时候将使用默认的值
    list=50
    port=8001
    def usage():
        print """
        -h --help             print the help
        -l --list             Maximum number of connections
        -p --port             To monitor the port number  
        """
    for op, value in opts:
        if op in ("-l","--list"):
            list = string.atol(value)
        elif op in ("-p","--port"):
            port = string.atol(value)
        elif op in ("-h"):
            usage()
            sys.exit()
    
    def jonnyS(client, address):
        try:
        #设置超时时间
            client.settimeout(500)
        #接收数据的大小
            buf = client.recv(2048)
        #将接收到的信息原样的返回到客户端中
            client.send(buf)
        #超时后显示退出
        except socket.timeout:
            print 'time out'
        #关闭与客户端的连接
        client.close()
    
    def main():
        #创建socket对象。调用socket构造函数
        #AF_INET为ip地址族,SOCK_STREAM为流套接字
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
        #将socket绑定到指定地址,第一个参数为ip地址,第二个参数为端口号
        sock.bind(('localhost', port))  
        #设置最多连接数量
        sock.listen(list) 
        while True:  
        #服务器套接字通过socket的accept方法等待客户请求一个连接
            client,address = sock.accept()  
            thread = threading.Thread(target=jonnyS, args=(client, address))
            thread.start()
    
    if __name__ == '__main__':
        main()

          为了防止客户数量过多而造成后面的客户等待,我设置了超时时间,虽然不能从更本解决这个问题,但是可以防止一些客户端白白占用着连接数而不工作,也算是总讨巧的方案了~而且通过传入参数的方式也可以方便的控制监听的端口号和允许最多的连接数,虽然没有考证过系统最多开启多少个进程,不过对于一个练习而言已经足够了,希望有人知道的话欢迎留言告诉我哈~

    下面是客户端的:

    #coding=utf-8
    import getopt,socket,sys,string
    
    opts, args = getopt.getopt(sys.argv[1:], "hi:p:",["help","ip=","port="])
    #设置默认的ip地址和端口号,在没有使用命令传入参数的时候将使用默认的值
    host="localhost"
    port=8001
    def usage():
        print """
        -h --help             print the help
        -i --ip               Enter the IP address to connect
        -p --port             Enter the port number to connect  
        """
    for op, value in opts:
        if op in ("-i","--ip"):
            host = value
        elif op in ("-p","--port"):
            port = string.atol(value)
        elif op in ("-h"):
            usage()
            sys.exit()
    
    def main():   
    #创建socket对象。调用socket构造函数
    #AF_INET为ip地址族,SOCK_STREAM为流套接字
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    #设置要连接的服务器的ip号和端口号
        sock.connect((host, port))
    #客户端输入一个字符串给服务器    
        message = raw_input("inupt:")
        #pdb.set_trace()
        sock.send(message)  
        print 'ServerOupt:'+ sock.recv(2048)
    #关闭与服务器的连接  
        sock.close()  
    
    if __name__ == '__main__': 
        main()

          客户端就相对简单的多了,很简单的一个读取用户输入,发送给服务器然后接收回来这样一个简单的功能,在设置过编码之后中文什么的也是可以的了~值得注意的就是recw()方法中设置的发送大小,太小的话会报错的~

          总体来说和我第一次用Java来实现的时候比起来,现在已经轻松容易的多了,不过也正好可以借此机会温习一下过去的知识了~学而不思则罔,思而不学则殆!

  • 相关阅读:
    SessionFactory Cache 的配置
    乱码处理问题
    格式化当前日期
    JDK的安装
    内存和对象内存池技术在网游开发中的注意点和应用
    Head First设计模式C++实现Strategy模式
    介绍三种将二进制字节字符转换为ASCII方法
    C++风格的类型转换的用法
    i++循环与i循环的执行效率
    系统程序员成长计划组合的威力(一)
  • 原文地址:https://www.cnblogs.com/fuhuixiang/p/4103608.html
Copyright © 2020-2023  润新知