精华内容
下载资源
问答
  • 求大神帮忙啊,开发了一个手机app的客户端和服务器端,客户端可以打包成一个apk直接在手机上安装,请问服务器端的servlet可不可以也这样,具体怎么
  • 上篇我用mina框架的socket写好了项目,后来一直纠结怎么在服务器上运行那个主类。终于,又是那个师兄提点了我。java项目打包成.jar文件,再用Lanuch4j工具生成.exe,然后运行在服务器就行了。 Lanuch4j下载地址 ...

    上篇我用mina框架的socket写好了项目,后来一直纠结怎么在服务器上运行那个主类。终于,又是那个师兄提点了我。java项目先打包成.jar文件,再用Lanuch4j工具生成.exe,然后运行在服务器就行了。

    Lanuch4j下载地址

    下面就截图好了,相信大家看得懂的。

    1、打包成成jar文件。


    2、打包成exe文件

    打开Lanuch4j工具,具体的配置步骤可以按照这个网址去弄, Lanuch4j为java 程序生成EXE可执行文件 

    最后直接点击运行exe文件就行了,在进程那里可以看见一个javaw.exe进程。


    展开全文
  • 主要还是想知道Deno的性能怎么样,用Deno能不能大幅减少前端构建项目的耗时。对网络上Deno能不能替代Node的讨论也比较感兴趣,于是便用Deno跟Node去执行一些常用的方法,比较它们的性能,研究下Deno是否可以替代Node...

    今年五月份Deno发布了1.0版本,作为一个经常用Node来构建项目的前端,对Deno官网描述的那几点优点其实并不太关心(Deno优点)。主要还是想知道Deno的性能怎么样,用Deno能不能大幅减少前端构建项目的耗时。对网络上Deno能不能替代Node的讨论也比较感兴趣,于是便用Deno跟Node去执行一些常用的方法,比较它们的性能,研究下Deno是否可以替代Node。

    Deno简介

    Deno是一个JavaScript和TypeScript运行时,跟Node、Java一样可以运行在服务器上。

    测试信息

    Node版本v14.6.0(v8-8.4.371.19),Deno版本1.1.0(v8-8.4.300)。
    执行结果是执行了5次相同方法取的范围。
    第三方库用了spark-md5、js-base64、acorn、estraverse和escodegen。

    用sort排序数组(数组长度为20万)

    console.time("sort-array");
    dataArray.sort((a, b) => {
      return a - b;
    });
    console.timeEnd("sort-array");

    node:79.034ms-101.74ms
    deno:134ms-140ms

    md5(文件大小为2.6M)

    console.time("md5");
    spark.append(data);
    console.log(`md5: ${spark.end()}`);
    console.timeEnd("md5");

    node 33.559ms-41.608ms
    deno 63ms-83ms

    base64(文件大小为2.6M)

    console.time("Base64");
    Base64.encode(data);
    console.timeEnd("Base64");

    node 572.197ms-662.004ms
    deno 1216ms-1269ms

    斐波那契数列(n=40)

    function fib(n) {
      if (n === 0) {
        return 0;
      } else if (n === 1) {
        return 1;
      } else {
        return fib(n - 1) + fib(n - 2);
      }
    }
    console.time("fib");
    fib(40);
    console.timeEnd("fib");

    node 1.286s-1.343s
    deno 1447ms-1616ms

    for in遍历对象(10万个属性)

    console.time("for in");
    for (let k in dataObject) {
      total += dataObject[k].list[0].n;
    }
    console.timeEnd("for in");

    node 49.773ms-65.803ms
    deno 41ms-49ms

    JSON 序列化(10万个属性)

    console.time("JSON");
    let result = JSON.parse(JSON.stringify(dataObject));
    console.timeEnd("JSON");

    node 345.198ms-376.225ms
    deno 173ms-192ms

    自定义loader(生成了大概202个文件)

    webpack打包项目中loader占用的时间挺多的,而最常用的babel-loader简单说是把文件转换成AST,处理AST之后再重新返回。我们可以模拟下这个过程。
    我的做法是复制acorn、estraverse和escodegen这三个文件,把这三个文件改成Deno可以引用的形式。然后自定义loader的代码处理逻辑Node跟Deno一样,都是读取目录下面的所有js文件,给所有js文件的函数名增加了一个自定义后缀,最后把重新生成的js文件输出到一个目录里。

    Deno使用的API:Deno.readTextFileSync、Deno.realPathSync、Deno.readDirSync、Deno.statSync、Deno.readTextFile、Deno.writeTextFile

    Node使用的API:path.resolve、fs.readdirSync、fs.statSync、fs.readFile、fs.writeFile
    node 2.371s-2.555s
    deno 2057ms-2417ms

    上面所有的测试代码都在这里,测试的结果应该会不同,但差异幅度应该是准确的。大家可以用自己的电脑跑跑看。

    性能比对分析

    从上面的数据我们可以看到Node在数组排序、函数递归调用、md5计算、base64编码的测试表现会好一点,而在JSON序列化、对象遍历、自定义loader的测试中Deno要表现更好。

    用webpack打包的话,自定义loader的测试比重应该是比其他项高的,所以Deno如果用来打包项目应该还是有一定提升的,从数据上看最高能提升20%左右。当然,这个结论并不准确,实际开发中webpack的处理还是比较复杂的,真正准确的对比还是要用Deno实现一个webpack。但就算是按20%的提升来说,也是太少了,不足以让人放弃webpack的生态。比如说Rollup跟Parcel都曾经宣传打包效率比webpack高很多,但他们现在都无法撼动webpack在构建工具中的领袖地位。

    所以说先发优势还是很重要的,现在Node的服务端框架有Express、构建工具有webpack、桌面端应用有electron,这些都是比较成熟的应用。Deno的实现如果没有高性能的优势还是很难去替代Node的。而且从Deno官网文档看到的是想替代Python的部分场景,而不是Node。详见这里。(谁叫Python那么慢呢^ ^)

    Deno使用体验

    首先Deno能直接执行typescript文件,不需要先用tsc进行编译。函数默认返回promise,可以直接使用await。支持import()跟web worker,使用体验跟在浏览端还是有点像的,容易上手。

    总得来说使用体验还是挺好的,比起Node的话就是省去了构建的功夫。

    但Deno目前并不成熟,一些API还不稳定,提供的API也太少了,一些Node上提供的便捷方法只能自己重新实现。而且还有部分还实现不了,比如os模块的一些方法(这个issue列出了一些不支持的方法)。第三方模块也还比较少,目前只有786个。具体可以查看这里。

    所以说虽然Deno发布了1.0版本,但是距离生产使用还是要再等一段时间的(不确定具体时间,感觉要等个3、5年吧= =)。

    总结

    1. 考虑重构成本跟生态强度,Deno的性能如果没有比Node高出很多是难以替代Node的。
    2. Deno应该也能抓住一部分用户,对Deno优点感兴趣的朋友也有不少,而且Deno的学习成本还是相对比较低的(用过Node的话)。
    3. 由于Deno目前的生态还不成熟,系统方法跟第三方库都还比较少,所以现在不建议企业公司在生产环境使用Deno。什么时候能用还是要看Deno生态的发展情况。

    转载标明出处即可。


    感谢jjc大佬的提醒,更新了Node版本,增加上v8的版本比对。


    文章仅仅对比的是部分方法的运行速度,不代表两个语言本身的性能快慢。服务端的性能可以看Deno官网的对比结果。

    Benchmarks | Denodeno.land
    e1a174304a09d52881021fe656ba356c.png
    展开全文
  • 最近公司开了新项目,对接不同的客户,并且后端服务是直接部署在客服的服务器上,这就要求我们的项目名,服务端地址必须跟客户对应。当然如果你一个一个的改,一个一个的打包,没问题,但是这样太麻烦了,费时费力,...

    前言

    最近公司开了新项目,对接不同的客户,并且后端服务是直接部署在客服的服务器上,这就要求我们的项目名,服务端地址必须跟客户对应。当然如果你一个一个的改,一个一个的打包,没问题,但是这样太麻烦了,费时费力,几十个客户,就要求你改几十次,重复打几十次包,想想都蛋疼。作为一个合格的程序员,怎么可能去做这么蠢的体力劳动,有这个时间,我都可以打完几局王者荣耀了,说不定都升入星耀了,ok,不扯淡了,直接上代码配置。

    配置

    由于我们并不要求logo也换,所以关于logo的配置我没有写,关于更细节的要求你可以参考这篇blog多渠道打包之动态修改App名称,图标,applicationId,版本号,添加资源

    1,在Manifest.xml配置我们的Channel_value

            <meta-data
                android:name="CHANNEL"
                android:value="${CHANNEL_VALUE}" />
    

    2,修改我们app下的build.gradle文件

    apply plugin: 'com.android.application'
    //配置时间
    def releaseTime() {
        return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC"))
    }
    
    android {
        compileSdkVersion 27
        buildToolsVersion '27.0.3'
    //TODO---因为我们要求app_name不同,所以一定不要在string.xml里面定义app_name,不然会报错
        defaultConfig {
            applicationId "com.kd.machine"
            minSdkVersion 19
            targetSdkVersion 27
            versionCode 1
            versionName "1.0.0"
            //resValue 其实跟string.xml直接写app_name一样,动态添加
            resValue "string", "app_name", "调试xxxx"
            //这里我定义了我们本地调试的服务器地址,我这里定义成了常量
            buildConfigField "String", "IpAddressAndPort", '"http://47.94.156.205:80"'
            //这里是我们调试的默认省份,,我这里定义成了常量
            buildConfigField "String", "Province", '"调试省份"'
            multiDexEnabled true
            //这里添加了调试渠道
            manifestPlaceholders = [
                    "OCR_API_KEY": "273a238bfb9871e94df6cd4319f56c38",
                    CHANNEL_VALUE: "sdkd"
            ]
    
            ndk {
                //Luban turbo
                abiFilters 'armeabi-v7a', 'x86'
            }
    
        }
    
    //这里是我们配置的渠道信息
        productFlavors {
    
            test {//这个是配置的测试环境渠道
                resValue "string", "app_name", "测试xxxx"
                buildConfigField "String", "IpAddressAndPort", '"http://47.94.156.205:80"'
    
                buildConfigField "String", "Province", '"测试省份"'
                // 修改 AndroidManifest.xml 里渠道变量
                manifestPlaceholders = ["OCR_API_KEY"  : "273a238bfb9871e94df6cd4319f56c38"
                                        , CHANNEL_VALUE: "test"
                ]
            }
    
        //下面的渠道,就是我们生产环境要求的
            shandong {
                resValue "string", "app_name", "山东xxxx"
                buildConfigField "String", "IpAddressAndPort", '"http://103.239.153.75:8000/"'
    
                buildConfigField "String", "Province", '"山东"'
                // 修改 AndroidManifest.xml 里渠道变量
                manifestPlaceholders = ["OCR_API_KEY"  : "273a238bfb9871e94df6cd4319f56c38"
                                        , CHANNEL_VALUE: "shandong"
                                       ]
            }
            shanxi {//山西
                resValue "string", "app_name", "山西xxxx"
                buildConfigField "String", "IpAddressAndPort", '"http://218.26.228.130:8000/"'
    
                buildConfigField "String", "Province", '"山西"'
    
                manifestPlaceholders = ["OCR_API_KEY"  : "273a238bfb9871e94df6cd4319f56c38"
                                        , CHANNEL_VALUE: "shanxi"
                                        ]
            }
            shanxii {//陕西
                resValue "string", "app_name", "陕西xxxx"
    
                buildConfigField "String", "IpAddressAndPort", '"http://1.85.55.167:8000/"'
    
                buildConfigField "String", "Province", '"陕西"'
    
                manifestPlaceholders = ["OCR_API_KEY"  : "273a238bfb9871e94df6cd4319f56c38"
                                        , CHANNEL_VALUE: "shanxii"
                                        ]
            }
            guangxi {//陕西
                resValue "string", "app_name", "广西xxxx"
    
                buildConfigField "String", "IpAddressAndPort", '"http://47.106.194.225:86/"'
    
                buildConfigField "String", "Province", '"广西"'
    
                manifestPlaceholders = ["OCR_API_KEY"  : "273a238bfb9871e94df6cd4319f56c38"
                                        , CHANNEL_VALUE: "guangxi"
                ]
            }
            hubei {//陕西
                resValue "string", "app_name", "湖北xxxx"
    
                buildConfigField "String", "IpAddressAndPort", '"http://nyt.hubei.gov.cn/"'
    
                buildConfigField "String", "Province", '"湖北"'
    
                manifestPlaceholders = ["OCR_API_KEY"  : "273a238bfb9871e94df6cd4319f56c38"
                                        , CHANNEL_VALUE: "hubei"
                ]
            }
            hunan {//陕西
                resValue "string", "app_name", "湖南xxxx"
    
                buildConfigField "String", "IpAddressAndPort", '"http://222.240.191.245:4318/"'
    
                buildConfigField "String", "Province", '"湖南"'
    
                manifestPlaceholders = ["OCR_API_KEY"  : "273a238bfb9871e94df6cd4319f56c38"
                                        , CHANNEL_VALUE: "hunan"
                ]
            }
            yunnan {//陕西
                resValue "string", "app_name", "云南xxxx"
    
                buildConfigField "String", "IpAddressAndPort", '"http://58.57.109.190:8000/"'
    
                buildConfigField "String", "Province", '"云南"'
    
                manifestPlaceholders = ["OCR_API_KEY"  : "273a238bfb9871e94df6cd4319f56c38"
                                        , CHANNEL_VALUE: "yunnan"
                ]
            }
            anhui {//陕西
                resValue "string", "app_name", "安徽xxxx"
    
                buildConfigField "String", "IpAddressAndPort", '"http://www.ahnjpt.cn:8000/"'
    
                buildConfigField "String", "Province", '"安徽"'
    
                manifestPlaceholders = ["OCR_API_KEY"  : "273a238bfb9871e94df6cd4319f56c38"
                                        , CHANNEL_VALUE: "anhui"
                ]
            }
            jilin {//陕西
                resValue "string", "app_name", "吉林xxxx"
    
                buildConfigField "String", "IpAddressAndPort", '"http://www.ahnjpt.cn:8000/"'
    
                buildConfigField "String", "Province", '"吉林"'
    
                manifestPlaceholders = ["OCR_API_KEY"  : "273a238bfb9871e94df6cd4319f56c38"
                                        , CHANNEL_VALUE: "jilin"
                ]
            }
            gansu {//陕西
                resValue "string", "app_name", "甘肃xxxx"
    
                buildConfigField "String", "IpAddressAndPort", '"http://61.178.243.120:18080/"'
    
                buildConfigField "String", "Province", '"甘肃"'
    
                manifestPlaceholders = ["OCR_API_KEY"  : "273a238bfb9871e94df6cd4319f56c38"
                                        , CHANNEL_VALUE: "gansu"
                ]
            }
            henan {//陕西
                resValue "string", "app_name", "河南xxxx"
    
                buildConfigField "String", "IpAddressAndPort", '"http://www.njjl.org:81/"'
    
                buildConfigField "String", "Province", '"河南"'
    
                manifestPlaceholders = ["OCR_API_KEY"  : "273a238bfb9871e94df6cd4319f56c38"
                                        , CHANNEL_VALUE: "henan"
                ]
            }
            qinghai {//陕西
                resValue "string", "app_name", "青海xxxx"
    
                buildConfigField "String", "IpAddressAndPort", '"http://www.qhnjjl.net:8000/"'
    
                buildConfigField "String", "Province", '"青海"'
    
                manifestPlaceholders = ["OCR_API_KEY"  : "273a238bfb9871e94df6cd4319f56c38"
                                        , CHANNEL_VALUE: "qinghai"
                ]
            }
            guangdong {//陕西
                resValue "string", "app_name", "广东xxxx"
    
                buildConfigField "String", "IpAddressAndPort", '"http://183.62.243.18:8770/"'
    
                buildConfigField "String", "Province", '"广东"'
    
                manifestPlaceholders = ["OCR_API_KEY"  : "273a238bfb9871e94df6cd4319f56c38"
                                        , CHANNEL_VALUE: "guangdong"
                ]
            }
            sichuan {//陕西
                resValue "string", "app_name", "四川xxxx"
    
                buildConfigField "String", "IpAddressAndPort", '"http://202.61.89.127:8000/"'
    
                buildConfigField "String", "Province", '"四川"'
    
                manifestPlaceholders = ["OCR_API_KEY"  : "273a238bfb9871e94df6cd4319f56c38"
                                        , CHANNEL_VALUE: "sichuan"
                ]
    
            }
    
            xinjiang {//陕西
                resValue "string", "app_name", "新疆xxxx"
    
                buildConfigField "String", "IpAddressAndPort", '"http://220.171.42.224:88/"'
    
                buildConfigField "String", "Province", '"新疆"'
    
                manifestPlaceholders = ["OCR_API_KEY"  : "273a238bfb9871e94df6cd4319f56c38"
                                        , CHANNEL_VALUE: "xinjiang"
                ]
    
            }
    
    
        }
    
    
    
        signingConfigs {
            config {
                storeFile file("debug.jks")
                storePassword "123456"
                keyAlias "machine"
                keyPassword "123456"
                v2SigningEnabled true
            }
    
        }
        buildTypes {
            debug {
                minifyEnabled false
                zipAlignEnabled true
                shrinkResources false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
                signingConfig signingConfigs.config
    
            }
    
            release {
                //混淆
                minifyEnabled true
                //Zipalign优化
                zipAlignEnabled true
                //移除无用的resource文件
                shrinkResources true
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
                signingConfig signingConfigs.config
    
                applicationVariants.all { variant ->
                    variant.outputs.each { output ->
                        def outputFile = output.outputFile
                        if (outputFile != null && outputFile.name.endsWith('.apk')) {
                            //apk命名格式:Agricultural_Machinery_Supervision_渠道号_版本号_发布时间.apk
                            def fileName = "Agricultural_Machinery_Supervision_${variant.productFlavors[0].name}_v${android.defaultConfig.versionName}_${releaseTime()}.apk"
                            output.outputFile = new File(outputFile.parent, fileName)
                        }
                    }
    
                }
    
            }
    
        }
    
    
    
        repositories {
            flatDir {
                dirs 'libs'
            }
        }
    
    
    
    
    }
    
    
    
    

    后续

    这个就跟我之前的多渠道打包要求不太一样,之前的多渠道,是给多个应用市场打不同的渠道包,只需要配置下渠道就行了,其它的都一样,所以用美团的walle多渠道打包很快就完事了,但是好像不太支持其它配置,当然很有可能是我不会用,所以我只能这样搞了,记录下,做个笔记,方便自己查找,在我的项目里,这个配置是可以的,如果你用了出错,可以留言交流哈。

    展开全文
  • 使用webpack打包vue后,将打包好的文件,发布到Tomcat上,访问成功,但是刷新后页面报404错。 在网上查找了一下,原来是HTML5 History 模式引发的问题,具体为什么,vue官方已经给出了解释,你可以看...
  • react 服务端路由配置

    2020-10-26 10:15:09
    npm run build 打包后放到java项目里,启动后,8080端口在首页后的跳转 出现404错误,网上搜了许多,说是后端没有配置路由,在8080跳转时会向服务器发送请求,后端没有配置,所以报404。 想问一下后端的路由我该...
  • 最近由于一个项目需要,写了一个简易的websocket服务端程序,其间也参考了网上的很多资料,我将用接下来的几个篇幅说明是怎么实现的,及遇到的一系列埂。参考 (包括且不限于如下地址)涉及到的模块socket:socket通讯...

    最近由于一个项目需要,写了一个简易的websocket服务端程序,其间也参考了网上的很多资料,我将用接下来的几个篇幅说明是怎么实现的,及遇到的一系列埂。

    参考 (包括且不限于如下地址)

    涉及到的模块

    socket:socket通讯如侦听端口接收数据、发送数据等部分需要

    struct:对发送和接收的数据包进行解包、打包等

    hashlib,base64:通过接收浏览器的key生成websocket会话所需要的token

    threading:实现多线程

    time:对时间的处理

    主要涉及到的函数

    get_datalength:此函数在建立websocket会话,接受用户发送的数据后调用,通过解包接收到的bytes信息计算出用户发送过来的数据总长度及数据帧头部的大小。websocket帧在封装不同长度的内容时头部大小是不一样的,需要此函数处理后计算出所有数据是否接收完毕。

    parser_data:浏览器在建立websocket会话后发送过来的bytes数据是有掩码加密的,此函数在建立websocket会话接受完用户发送的所有数据后调用,提取出用户发送过来的实际内容。

    sendMessage:在建立websocket会话后,服务端通过socket通道发送数据到浏览器端时调用此函数,主要作用是在实际数据包头部增加websocket数据特有的帧。

    定义到的类

    WebSocketServer : WebSocket服务器对象,调用此类的begin方法后将开启服务端程序。

    WebSocket:threading.Thread类的子类,处理每一个连接请求。

    服务端代码

    # coding: utf-8

    import socket

    import struct

    import hashlib,base64

    import threading

    import time

    connectionlist = {} #存放链接客户fd,元组

    g_code_length = 0

    g_header_length = 0 #websocket数据头部长度

    PRINT_FLAG = True

    """

    经测试发现IE 11浏览器在成功建立websocket连接后,会间隔30s发送空信息给服务器以验证是否处于连接状态,

    因此服务区需要对收到的数据进行解码并判断其中载荷内容是否为空,如为空,应不进行广播

    """

    # 计算web端提交的数据长度并返回

    def get_datalength(msg):

    global g_code_length

    global g_header_length

    g_code_length = msg[1] & 127

    if g_code_length == 126:

    g_code_length = struct.unpack('>H', msg[2:4])[0]

    g_header_length = 8

    elif g_code_length == 127:

    g_code_length = struct.unpack('>Q', msg[2:10])[0]

    g_header_length = 14

    else:

    g_header_length = 6

    g_code_length = int(g_code_length)

    return g_code_length

    # 解析web端提交的bytes信息,返回str信息(可以解析中文信息)

    def parse_data(msg):

    global g_code_length

    g_code_length = msg[1] & 127

    if g_code_length == 126:

    g_code_length = struct.unpack('>H', msg[2:4])[0]

    masks = msg[4:8]

    data = msg[8:]

    elif g_code_length == 127:

    g_code_length = struct.unpack('>Q', msg[2:10])[0]

    masks = msg[10:14]

    data = msg[14:]

    else:

    masks = msg[2:6]

    data = msg[6:]

    en_bytes = b""

    cn_bytes = []

    for i, d in enumerate(data):

    nv = chr(d ^ masks[i%4])

    nv_bytes = nv.encode()

    nv_len = len(nv_bytes)

    if nv_len == 1:

    en_bytes += nv_bytes

    else:

    en_bytes += b'%s'

    cn_bytes.append(ord(nv_bytes.decode()))

    if len(cn_bytes) > 2:

    cn_str = ""

    clen = len(cn_bytes)

    count = int(clen / 3)

    for x in range(count):

    i = x * 3

    b = bytes([cn_bytes[i], cn_bytes[i + 1], cn_bytes[i + 2]])

    cn_str += b.decode()

    new = en_bytes.replace(b'%s%s%s', b'%s')

    new = new.decode()

    res = (new % tuple(list(cn_str)))

    else:

    res = en_bytes.decode()

    return res

    # 调用socket的send方法发送str信息给web端

    def sendMessage(msg):

    global connectionlist

    send_msg = b"" #使用bytes格式,避免后面拼接的时候出现异常

    send_msg += b"\x81"

    back_str = []

    back_str.append('\x81')

    data_length = len(msg.encode()) #可能有中文内容传入,因此计算长度的时候需要转为bytes信息

    if PRINT_FLAG:

    print("INFO: send message is %s and len is %d" % (msg, len(msg.encode('utf-8'))))

    # 数据长度的三种情况

    if data_length <= 125:#当消息内容长度小于等于125时,数据帧的第二个字节0xxxxxxx 低7位直接标示消息内容的长度

    send_msg += str.encode(chr(data_length))

    elif data_length <= 65535:#当消息内容长度需要两个字节来表示时,此字节低7位取值为126,由后两个字节标示信息内容的长度

    send_msg += struct.pack('b', 126)

    send_msg += struct.pack('>h', data_length)

    elif data_length <= (2^64-1):#当消息内容长度需要把个字节来表示时,此字节低7位取值为127,由后8个字节标示信息内容的长度

    send_msg += struct.pack('b', 127)

    send_msg += struct.pack('>q', data_length)

    else:

    print (u'太长了')

    send_message = send_msg + msg.encode('utf-8')

    for connection in connectionlist.values():

    if send_message != None and len(send_message) > 0:

    connection.send(send_message)

    #删除连接,从集合中删除连接对象item

    def deleteconnection(item):

    global connectionlist

    del connectionlist['connection'+item]

    #定义WebSocket对象(基于线程对象)

    class WebSocket(threading.Thread):

    def __init__(self,conn,index,name,remote, path=""):

    #初始化线程

    threading.Thread.__init__(self)

    #初始化数据,全部存储到自己的数据结构中self

    self.conn = conn

    self.index = index

    self.name = name

    self.remote = remote

    self.path = path

    self.GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"

    self.buffer = ""

    self.buffer_utf8 = b""

    self.length_buffer = 0

    def generate_token(self, WebSocketKey):

    WebSocketKey = WebSocketKey + self.GUID

    Ser_WebSocketKey = hashlib.sha1(WebSocketKey.encode(encoding='utf-8')).digest()

    WebSocketToken = base64.b64encode(Ser_WebSocketKey) # 返回的是一个bytes对象

    return WebSocketToken.decode('utf-8')

    #运行线程

    def run(self):

    #Log输出,套接字index启动

    if PRINT_FLAG:

    print('Socket %s Start!' % self.index)

    global g_code_length

    global g_header_length

    self.handshaken = False #Socket是否握手的标志,初始化为false

    while True:

    if self.handshaken == False: #如果没有进行握手

    if PRINT_FLAG:

    print('INFO: Socket %s Start Handshaken with %s!' % (self.index,self.remote))

    self.buffer = self.conn.recv(1024).decode('utf-8') #socket会话收到的只能是utf-8编码的信息,将接收到的bytes数据,通过utf-8编码方式解码为unicode编码进行处理

    if PRINT_FLAG:

    print("INFO: Socket %s self.buffer is {%s}" % (self.index, self.buffer))

    if self.buffer.find('\r\n\r\n') != -1:

    headers = {}

    header, data = self.buffer.split('\r\n\r\n', 1) #按照这种标志分割一次,结果为:header data

    #对header进行分割后,取出后面的n-1个部分

    for line in header.split("\r\n")[1:]: #再对header 和 data部分进行单独的解析

    key, value = line.split(": ", 1) #逐行的解析Request Header信息(Key,Value)

    headers[key] = value

    try:

    WebSocketKey = headers["Sec-WebSocket-Key"]

    except KeyError:

    print("Socket %s Handshaken Failed!" % (self.index))

    deleteconnection(str(self.index))

    self.conn.close()

    break

    WebSocketToken = self.generate_token(WebSocketKey)

    headers["Location"] = ("ws://%s%s" %(headers["Host"], self.path))

    #握手过程,服务器构建握手的信息,进行验证和匹配

    #Upgrade: WebSocket 表示为一个特殊的http请求,请求目的为从http协议升级到websocket协议

    handshake = "HTTP/1.1 101 Switching Protocols\r\n"\

    "Connection: Upgrade\r\n"\

    "Sec-WebSocket-Accept: " + WebSocketToken + "\r\n"\

    "Upgrade: websocket\r\n\r\n"

    self.conn.send(handshake.encode(encoding='utf-8')) # 前文以bytes类型接收,此处以bytes类型进行发送

    # 此处需要增加代码判断是否成功建立连接

    self.handshaken = True #socket连接成功建立之后修改握手标志

    #向全部连接客户端集合发送消息,(环境套接字x的到来)

    sendMessage("Welocomg " + self.name + " !")

    g_code_length = 0

    else:

    print("Socket %s Error2!" % (self.index))

    deleteconnection(str(self.index))

    self.conn.close()

    break

    else:

    # 每次接收128字节数据,需要判断是否接收完所有数据,如没有接收完,需要循环接收完再处理

    mm = self.conn.recv(128)

    #计算接受的长度,判断是否接收完,如未接受完需要继续接收

    if g_code_length == 0:

    get_datalength(mm) # 调用此函数可以计算并修改全局变量g_code_length和g_header_length的值

    self.length_buffer += len(mm)

    self.buffer_utf8 += mm

    if self.length_buffer - g_header_length < g_code_length:

    if PRINT_FLAG:

    print("INFO: 数据未接收完,接续接受")

    continue

    else:

    if PRINT_FLAG:

    print("g_code_length:", g_code_length)

    print("INFO Line 204: Recv信息 %s,长度为 %d:" % (self.buffer_utf8, len(self.buffer_utf8)))

    if not self.buffer_utf8:

    continue

    recv_message = parse_data(self.buffer_utf8)

    if recv_message == "quit":

    print("Socket %s Logout!" % (self.index))

    nowTime = time.strftime('%H:%M:%S',time.localtime(time.time()))

    sendMessage("%s %s say: %s" % (nowTime, self.remote, self.name+" Logout"))

    deleteconnection(str(self.index))

    self.conn.close()

    break

    else:

    nowTime = time.strftime('%H:%M:%S',time.localtime(time.time()))

    sendMessage("%s %s say: %s" % (nowTime, self.remote, recv_message))

    g_code_length = 0

    self.length_buffer = 0

    self.buffer_utf8 = b""

    #WebSocket服务器对象()

    class WebSocketServer(object):

    def __init__(self):

    self.socket = None

    self.i = 0

    #开启操作

    def begin(self):

    if PRINT_FLAG:

    print('WebSocketServer Start!')

    self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    ip = '10.1.80.83'

    port = 8080

    if PRINT_FLAG:

    print("WebServer is listening %s,%d" % (ip,port))

    self.socket.bind((ip,port))

    self.socket.listen(50)

    #全局连接集合

    global connectionlist

    while True:

    #服务器响应请求,返回连接客户的信息(连接fd,客户地址)

    connection, address = self.socket.accept()

    #根据连接的客户信息,创建WebSocket对象(本质为一个线程)

    #sockfd,index,用户名,地址

    newSocket = WebSocket(connection,self.i,address[0],address)

    #线程启动

    newSocket.start()

    #更新连接的集合(hash表的对应关系)-name->sockfd

    connectionlist['connection'+str(self.i)]=connection

    self.i += 1

    if __name__ == "__main__":

    server = WebSocketServer()

    server.begin()

    html页面代码

    WebSocket

    html,body{font:normal 0.9em arial,helvetica;}

    #log {width:440px; height:200px; border:1px solid #7F9DB9; overflow:auto;}

    #msg {width:440px;}

    var socket;

    function init(){

    var host = "ws://10.1.80.83:8080/";

    try{

    socket = new WebSocket(host);

    socket.onopen = function(msg){

    console.log("socket session create sucess!");

    log("socket session create sucess!");

    };

    socket.onmessage = function(msg){

    console.log("message Sucess");

    //socket.send("Hello");

    //log(msg.data);

    log(msg.data)

    };

    socket.onclose = function(msg){ console.log("close Sucess"); log("Connection Lose!"); };

    socket.onerror = function(msg){ console.log("Error!"); };

    }catch(ex){

    log(ex);

    }

    $("msg").focus();

    }

    function send(){

    var txt,msg;

    txt = $("msg");

    msg = txt.value;

    console.log("message is", msg)

    if(!msg){

    alert("Message can not be empty");

    return;

    }

    txt.value="";

    txt.focus();

    try{

    //log(msg);

    socket.send(msg);

    }catch(ex){

    log(ex);

    }

    }

    window.οnbefοreunlοad=function(){

    try{

    socket.send('quit');

    socket.close();

    socket=null;

    }catch(ex){

    log(ex);

    }

    };

    function $(id){

    return document.getElementById(id);

    }

    function log(msg){

    $("log").innerHTML+="
    "+msg;

    }

    function onkey(event){

    if(event.keyCode==13){

    send();

    }

    }

    WebSocket

    发送

    展开全文
  • 相比其他框架,优势在于直接发行,开发者无需在编译后代码上做二次开发或补充,可直接上传发布到服务端,这“可能”是社区里支持小程序、H5跨端最彻底的框架。背景2.随着微信小程序的火爆及百度、头条小程序的持续...
  • 原问题问题是这样呢我和iOS两...将这个代码打包成.war文件上传到服务器后,接收到iOS客户端的报文就是空字符串了(不是null哦),但是Android又是正常的,这是怎么回事呢?PS:我的PC是Mac,服务端是CentOS7 系统。//...
  • 原问题问题是这样呢我和iOS两...将这个代码打包成.war文件上传到服务器后,接收到iOS客户端的报文就是空字符串了(不是null哦),但是Android又是正常的,这是怎么回事呢?PS:我的PC是Mac,服务端是CentOS7 系统。//...
  • 《Linux多线程服务端编程:使用muduo C++网络库》主要讲述采用现代C++在x86-64 Linux上编写多线程TCP网络服务程序的主流常规技术,重点讲解一种适应性较强的多线程服务器的编程模型,即one loop per thread。...
  • 研究下webpack打包

    2020-07-18 21:09:19
    也很小,那么怎么解释,首先,性能优化不是单个方面的内容,它涉及到架构,服务器,服务端,中间键,浏览器,缓存,状态共享,打包压缩,浏览器加载时间等多个方面。 今天我们只谈谈前端打包,如何做到性能优化,...
  • 众所周知,我们在做前后端分离项目的时候,经常需要在本地起前端工程,接口希望拉取服务端的实际数据而不是本地的mock数据,而如果本地程序直接访问远程接口, 肯定会遇到跨域问题。 什么是跨域?实现跨域的多种方式? ...
  • 本文来讲讲,在本地开发完成后怎么在服务器上配合nginx部署node项目。 技术栈: nuxt.js -- 2.9.2 nginx -- 1.10.3 pm2 -- 3.5.1 node -- v10.16.3 npm -- 6.9.0 步骤: 本地打包、上传到服务器 安装服务器环境 ...
  • Android 上百实例源码分析以及开源分析 集合打包4

    千次下载 热门讨论 2012-07-10 21:54:03
    在Jamendo中,主要是通过再定义一个SeparatedListAdapter来进行这个工作,我们来看看它是怎么实现的:我理解的Adapter过程,首先通过调用getCount()来获得总Row数目,然后对一行调用getView进行绘制,因此要实现在...
  • 今天突然想将以前下载的一个vue企业官网项目部署到自己的阿里云服务器上,但是将项目打包后请求服务端的地址都出现了错误,改了许就都没成功,可能是因为前端与后端的请求地址做了其他捆绑操作吧,暂时没想到应该...
  • 看上去没啥毛病,但对于有追求,有上进心的你来说,你也想知道一个项目在破土动工前,前端leader是怎么搭建一个前端项目的工作流的,如何去手动配置一个具体项目的webpack打包文件,包括后期的SSR,服务端渲染。...
  • CAS 官方推荐使用 CAS overlay 打包 cas.war 来部署 CAS 服务端。 作为码农,上战场怎么能不带刀枪?!今天咱们就来说说使用 IDEA 该怎么搭建 CAS overlay 开发环境。 首先找到 Github 上 CAS overlay 的官方源码...
  • js 动态多图片下载

    2019-09-30 16:28:35
    最近项目中 有个需求 : 一个订单 可能存在 对张的电子发票 ,且 电子发票从接口中 获取的数据...产生了两个想法 :一: 采用 c# 服务端 进行图片流的 打包 并下载 (但是这个方法偏难了 ,所以我果断的舍弃了)  ...
  • 开发项目域名想怎么换就怎么换,就是这么任性! 这是一个很有意思的小工具!...很是麻烦,而且另外一个不得不正视的问题就是:只要跟服务端人员进行联调时,就得修改项目中的测试域名,重新打包,...
  • 至于pdf预览功能,使用第三方应用打开即可,在《作为一个java后端程序员,我是怎么接手android项目,并完成移动端的pdf处理需求的?》中我列出了处理过程中遇到的问题。 项目不大,主要功能就是这些,因为是传统企业...
  • 随便你怎么拆分服务器。只需要修改极少的代码就可以进行拆分。不同的server挂上不同的组件就行了嘛! 3.跨平台的分布式服务端 ET框架使用C#做服务端,现在C#是完全可以跨平台的,在linux上安装.netcore,即可,不...
  • 要求高:页面性能优化(CDN/异步加载/请求合并),CSS兼容性,单页面应用,服务端渲染。。。 怎么做到前端工程化? 从业务着手 简单的单页面应用,使用gulp打包 +同步工具实现开发全流程 从复杂度考虑 jenkenis
  • 但是,短信验证怎么实现呢?很多开发者有时会出现暂时的迷茫。下面我就把大概的思路告诉大家。一、申请短信通道,国内的短信通道很多,不同的通道速度不一样,我们在申请时要一个基本原则就是速度要快,基本上要发送...
  • 天猫启动了MAP项目(Tmall Front-end Architechture & Publish Mechanism)。 当时团队面临了一些大部分前端团队都困扰的难题,这部分阶段称为MAP 1.0。 1. 团队有一定规模,但是开发规范、工具、流程...
  • 以 <a href="https://github.com/Lucifier129/Isomorphism-react-todomvc">Isomorphism-react-todomvc</a> 这个项目为示例。它很可能是目前实现最完备的 react/redux todomvc demo,包含 react/redux 服务端...
  • 测试的话,可以运行本项目提供的服务端程序socket_server,在Android studio要先将服务端程序添加配置上去,具体怎么操作可以参考我的博客,地址:https://blog.csdn.net/liuxingrong666/article/details/91579548 ...
  • 这我们需要把<code>node_modules和<code>package.json打包进镜像 而官方的 node 镜像<code>node:8-alpine是不安装依赖的,需要我们自定义一个镜像 创建一个 <code>Dockerfile</code></p> <pre><code>...
  • 13.5 项目程序签名、打包和发布 257 13.6 本章小结 259 第14章 Android综合案例三——基于Android的豆瓣网(Web2.0)移动客户端开发 260 14.1 关于豆瓣网和豆瓣网API 260 14.1.1 豆瓣网介绍 260 14.1.2 豆瓣网API...
  • Tomcat是Apache组织下Jakarta项目下的一个子项目,它的主网站是:/index。JSP,Weblogic的在线文档:/ 。 3、IBM Webshpere Websphere同样可以下载到免费的试用版本,到IBM的developerWorks网站可以看到Websphere...

空空如也

空空如也

1 2
收藏数 38
精华内容 15
关键字:

服务端项目怎么打包