在日常工作中,需要对抓包后的数据在调试时重放。由于UDP头限定等问题,会造成传统UDP包发送无法被程序接收。此处列出一种可以重放保存的UDP pcap包的方法。

  1. 安装bittwist, 此工具能够修改pcap包,其他修改pcap包的工具(如NetDude)也能用,但是此处我们使用bittwist处理

  2. 获取需要接收UDP的机器的IP地址,此处我们用本机地址。输入ip address命令, 我们需要IP地址和mac地址,此处为192.168.1.1069c:b6:d0:bf:1f:8b

    1
    2
    3
    4
    5
    6
    2: wlp59s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 9c:b6:d0:bf:1f:8b brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.106/24 brd 192.168.1.255 scope global dynamic noprefixroute wlp59s0
    valid_lft 4881sec preferred_lft 4881sec
    inet6 fe80::bd4a:cb93:1b2e:2ca0/64 scope link noprefixroute
    valid_lft forever preferred_lft forever
  3. 使用bittwiste修改pcap包, 如果不修改,导致验证不一致,UDP包会被丢弃

    1
    2
    3
    4
    5
    6
    # 修改为接收放端口
    bittwiste -I 0316.pcap -O 0316-port.pcap -T udp -d 3002
    # 修改发送方和接收方IP
    bittwiste -I 0316-port.pcap -O 0316-port-ip.pcap -T ip -s 192.168.1.106 -d 192.168.1.106
    # 修改发送方和接收方MAC地址
    bittwiste -I 0316-port-ip.pcap -O 0316-port-ip-mac.pcap -T eth -s 9c:b6:d0:bf:1f:8b -d 9c:b6:d0:bf:1f:8b
  4. 发送UDP包,此处我们使用github上的一个开源工具udpreplay

    1
    udpreplay -i wlp59s0 0316-new-ip2-mac.pcap

至此UDP包能够在接收方Linux程序收到消息了。

如今网卡更新的速度已经超过操作系统的更新速度了,特别是开源操作系统,默认的网卡驱动动不动就跟不上新的主板,导致新的电脑无法识别到网卡,特别闹心。比如最近配置的Z390 Phantom Gaming SLI/ac这个主板,在ubuntu 18.04上,就是安装了ubuntu-18.04-hwe-generic,也没有找到对应的驱动程序,这个时候就需要手动安装了。在官网上下载好对应的驱动,注意我们是2.5G Ethernet LINUX driver r8125 for kernel up to 4.15的版本,不要下错了。如果是1G网卡,则对应GBE Ethernet LINUX driver r8168 for kernel up to 4.15版本。

下载好之后,当前版本是r8125-9.003.02.tar.bz2。里面有README文件,如果按照README安装,当时能够使用,但是重启或者升级内核版本之后,就失效了。所以还需要手动处理下。

  • 准备编译环境

    1
    sudo apt-get install --reinstall linux-headers-$(uname -r) linux-headers-generic build-essential dkms
  • 解压对应的源码到/usr/src

    1
    sudo tar xvf r8125-9.003.02.tar.bz2 -C /usr/src
  • 添加一个dkms.conf/usr/src/8125-9.003.02/dkms.conf,内容如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    PACKAGE_NAME=Realtek_r8125
    PACKAGE_VERSION=9.003.02

    DEST_MODULE_LOCATION=/updates/dkms
    BUILT_MODULE_NAME=r8125
    BUILT_MODULE_LOCATION=src/

    MAKE="'make' -C src/ all"
    CLEAN="'make' -C src/ clean"
    AUTOINSTALL="yes"
  • 编译DKMS

    1
    2
    3
    4
    5
    sudo dkms add -m r8125 -v 9.003.02
    sudo dkms build -m r8125 -v 9.003.02
    sudo dkms install -m r8125 -v 9.003.02
    sudo depmod -a
    sudo modprobe r8125
  • 验证安装结果, 运行如下命令即可看到enxxx的有线网接口

    1
    ifconfig -a

有时候在编写gitbook的时候,一个版本的内容需要按照编译参数给出不同的结果。比如内部版和外部版就会有一些差异,这个时候如何控制编译结果呢?
这里引入gitbook的一个参数功能。

  1. book.json中定义对应的控制参数

    1
    2
    3
    4
    5
    {
    "variables": {
    "version": "out"
    }
    }
  2. 在需要控制的内容块上使用条件判断

    1
    2
    3
    4
    5
    {% if book.version == "out" %}

    {% else %}

    {% endif %}

最近使用vagrant在macOS下进行PHP的开发,由于一直没法用xdebug调试,开发过程极其痛苦。折腾了半天终于折腾好了。记下步骤,免得下次再折腾。

  1. 在php运行环境内配置xdebug,我的vagrant环境是Ubuntu,故安装过程很简单
    1
    sudo apt-get install php70-xdebug
    安装后,打开xdebug配置文件,添加如下配置:
    1
    2
    3
    4
    5
    6
    7
    8
    zend_extension=xdebug.so
    xdebug.remote_enable=1
    xdebug.remote_port=19000 #注意,这里的端口最好不要用默认的9000,因为macOS的安全限制还是什么的,9000无发访问。在这里折腾了好久
    xdebug.remote_start =1
    xdebug.idekey="vagrant" #使用和PhpStorm内配置相同的key即可
    xdebug.remote_autostart=1
    xdebug.remote_connect_back=1
    xdebug.remote_handler=dbgp
  2. 在PhpStorm内配置PHP运行环境 一定要选vagrant
  3. 配置xdebug的监听端口,注意这里的端口要填写和xdebug.ini内一致的
  4. 填写server配置,其中host和port填写网站的访问地址和端口,文件映射一定要配置正确
  5. 点击PhpStorm的右上角的下拉的调试配置,Edit Configurations,添加Php Remote Debug调试配置。其中ide key填写和xdebug的配置文件相同的,server选择上一步填写的
  6. 点击右上角的电话按钮和debug按钮,添加断点,开始调试

在ARC下,iOS开发终于可以自动管理内存了。然而iOS内的Core Foundation对象仍然不能自动进行管理(如Core Graphics、Core Text等)。如果我们的程序需要访问CF对象是,仍然需要手动对其进行管理。当我们创建一个CF对象后,我们需要使用CFRelease对其进行手动释放操作。但是当CF和OC对象进行了转化的时候,又该如何管理呢?在这里OC提供了一下几个关键字对其进行操作。

  1. __bridge:CF和OC对象进行转化的时候只涉及对象类型转换,而不涉及对象所有权的额转换

    1
    2
    NSURL *url = [[NSURL alloc] initWithString:@"http://www.baidu.com"];
    CFURLRef ref = (CFURLRef)url;

    上面的代码在ARC下需要改成如下:

    1
    2
    NSURL *url = [[NSURL alloc] initWithString:@"http://www.baidu.com"];
    CFURLRef ref = (__bridge CFURLRef)url;

    由于url是OC创建的对象,并且在转换的过程中并不涉及对象所有权的转换,也就是说这个对象仍然会在OC中被释放,所以不需要调用CFRelease

    同理,如果一个对象在CF中创建,并用__bridge在OC中使用,则需要使用CFRelease进行释放操作。

  2. __bridge_transfer: CF对象转换成OC对象时,将CF对象的所有权交给OC对象,此时ARC就能自动管理该内存(作用同CFBridgingRelease())

  3. __bridge_retained:与__bridge_transfer相反,常用在将OC对象转换成CF对象时,将OC对象的所有权交给CF对象来管理(作用同CFBridgingRetain())

    1
    2
    3
    NSURL *url = [[NSURL alloc] initWithString:@"http://www.baidu.com"];
    CFURLRef ref = (__bridge_retained CFURLRef)url;
    CFRelease(ref);

    当使用_bridge_retained标识符以后,代表OC要将对象所有权交给CF对象自己来管理,所以我们要在ref使用完成以后用CFRelease将其手动释放.

    1
    2
    CFStringRef cfstring = CFURLCreateStringByAddingPercentEscapes(NULL,(__bridge CFStringRef)text, NULL, CFSTR("!*’();:@&=+\$,/?%#[]"), CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
    NSString *ocString = (__bridge_transfer CFStringRef)cfString;

    此时OC即获得了对象的所有权,ARC负责自动释放该对象,如果我们在结尾加上CFRelease(cfString)纯属画蛇添足,虽不会崩溃,但是控制台会打印出该对象被free了两次。

文章来源:请尊重作者

最近在尝试将项目的静态SDK库打包成cocoapods,以方便第三方用户使用。由于是第一次打包cocoapods,并且项目自身的代码和编译都不能改变,所以只能通过项目编译出的静态库.a文件和头文件.h文件直接提供,与cocoapods官方的文档上有很大的差异(在这里吐槽下,官方文档实在太简陋了,这么多人使用的项目,上手难度还是觉得挺大的)。所以在这里记录下提供静态库所遇到的问题,方便以后使用。

  1. 准备静态库文件libTest.a (此处必须是lib*.a这样的文件名格式,经过测试,xcode在编译的时候只能链接以lib作为prefix的静态库文件,否则会报链接失败)和Test.h文件

  2. 将文件放入文件夹,文件结构如下

    1
    2
    3
    Test
    ├── Test.h
    └── libTest.a
  3. 新建podspec文件,这里你可以自己手动新建,也可以使用cocoapods提供的命令来新建一个模板,再手动修改

    1
    pod spec create Test

    新建完成后的文件路径如下

    1
    2
    3
    4
    5
    .
    ├── Test
    │   ├── Test.h
    │   └── libTest.a
    └── Test.podspec

    修改Test.podspec文件,然后将此文件转为json文件(我也不知道为什么需要转成json文件,但是cocoapods的官方库里的spec文件都已经转成了json), 转成json文件的命令可以通过cocoapods的一个命令完成:

    1
    pod ipc spec Test.podspec

    最后的结果如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
     {
    "name": "Test",
    "version": "1.0.0",
    "summary": "Test",
    "description": "Test",
    "homepage": "https://yeluolei.github.io/",
    "license": {
    "type": "Copyright",
    "text": "Copyright 2016. All rights reserved."
    },
    "authors": {
    "yeluolei": "yeluolei@gmail.com"
    },
    "platforms": {
    "ios": "7.0"
    },
    "source": {
    "git" : "~/Test/"
    },
    "source_files": "Test/Test.h",
    "public_header_files": "Test/Test.h",
    "vendored_libraries": [
    "Test/libTest.a"
    ],
    "frameworks": [
    "JavaScriptCore",
    "Security",
    "CoreLocation",
    "SystemConfiguration",
    "CoreTelephony",
    "CoreGraphics",
    "UIKit",
    "Foundation"
    ],
    "libraries": [
    "z",
    "stdc++"
    ],
    "requires_arc": true
    }

    其中:

    • source 指定文件的来源,可以支持git,zip包等格式
    • source_files 指定文件需要引入的源代码文件,这里注意只需要包括源代码文件,不需要包括.a文件
    • public_header_files 第三方项目可以访问的公开的头文件
    • vendored_libraries 我们提供的静态库文件放在此处
    • frameworks 静态库依赖的动态库文件
    • libraries 静态库依赖的系统库文件
    • verdered_frameworks 如果需要的不是静态库,而是动态库.framework文件,则同理可以加在这里
  4. 将上面的文件全部放入git内,由于是测试使用,所以不需要将git push到远程服务器也可以

    1
    2
    3
    git init
    git add -A
    git commit -am 'init'
  5. 验证缩写的Test.podsspec.json文件是正确的,这里可以使用cocoapods官方提供的验证命令

    1
    pod spec lint --verbose
  6. 创建一个项目来测试

    • 新建一个xcode项目

    • 在项目文件夹新建一个Podfile文件,内容如下

      1
      2
      3
      4
      platform :ios, '9.0'
      target 'SampleProject' do
      pod 'Test',:path => '../Test/Test.podspec.json'
      end
    • 运行 pod install 命令

    • 打开xcode项目,可以看到我们的静态库和头文件已经被引入到项目内

  7. 上传到cocoapods(注意需要先把git改为真实的git才可以),这里要注意cocoapods现在需要先注册才能使用

    1
    pod trunk register 你的邮箱 '用户名' --description='简单描述'
  8. 完成邮箱验证后既可以把自己的代码库push到trunk上

    1
    pod trunk push Test.podsspec.json

至此,一个全新的cocoapods部署完成啦,回过头来看看还是挺简单的。