技术标签: WinPcap java TCP包 《互联网程序设计(Java)》——课程笔记 JPCAP 互联网程序设计 网络安全 抓包 计算机网络 发包
通常情况下网卡(工作在链路层)只往上层(网络层)传递3类包:广播包、与自己IP地址一致的单播包、已加入某组的组播包,在这种情况下,高层应用只能收到上述3类数据包。我们前几讲的程序设计工作,包括基于TCP Socket的网络应用(网络聊天、FTP、Email及HTTP),以及基于UDP Socket的网络聊天应用中,网卡只往网络层传递与自己IP地址一致的单播包。
抓包的思想是:流经网卡所有的有效包(经过链路层验证的)都要抓,所以抓包程序都是工作在链路层或网络层(不存在应用层的端口参数问题)。
网络抓包软件或工具,也叫网络嗅探器,目前网上有许多免费的嗅探软件。本教学单元基于JPCAP类库包(第三方软件包)自己动手开发抓/发包类工具软件。
1 JPCAP简介
Jpcap是一个能够捕获、发送网络数据包的java类库包。这个包用到了一些和操作系统有关的原始套接字API,目前,Jpcap支持Linux , Solaris和Windows 系列等操作系统。
对于Windows平台(http://www.winpcap.org/)需要安装WinPcap;
安装Winpcap,Winpcap是windows平台下的一个免费的,公共的网络访问系统(Linux系统是Libpcap),Jpcap就是调用Winpcap给java提供一个公共的接口,从而实现平台无关性,并能够捕获发送数据包.
1.2 JPCAP的类库结构
Jpcap0.4版本共有1个接口14个类,分别简介如下:
1、 接口综述
JpcapHandler :这个接口用来定义分析被捕获数据包的方法
2、 类综述
Jpcap :它用来捕获数据包,继承了java.lang.Object
Packet类:是所有被捕获的数据包的基类,继承了java.lang.Object;
IPPacket类:描述了IP包,继承了Packet类,支持IPv4和IPv6;
TCPPacket类:描述TCP包,继承了IPPacket类;
UDPPacket类:描述了UDP包,继承了IPPacket类;
ARPPacket类:描述了ARP/RARP包,继承了Packet类;
DatalinkPacket类:抽象类,描述了数据链路层的包,它继承了java.lang.Object;
EthernetPacket类:描述了以太帧包,继承DatalinkPacket类;
ICMPPacket类:描述了ICMP包,继承了IPPacket类;
IPAddress类:继承了java.lang.Object,描述了IPv4和IPv6地址,包含了将IP地址转换为域名的方法;
IPv6Option类:继承了java.lang.Object,描述了IPv6选项报头;
JpcapSender :它用来发送一个数据包,继承了java.lang.Object;
JpcapWriter :它用来将一个被捕获的数据包保存到文件,继承了java.lang.Object。
2 程序设计第一步:JPCAP程序设计环境配置
2.1 JPCAP的安装
针对Windows 环境:
1) 复制Jpcap压缩包中的"lib\Jpcap.dll"到java安装目录的"[jre directory]\bin"或java的"[jre directory]\lib\ext"中。
2) 复制Jpcap压缩包中的"lib\jpcap.jar"到java安装目录的"[jre directory]\lib\ext"中。
3) 还需要拷贝Jpcap压缩包中的"lib\jpcap.jar"到java安装目录的"[jdk directory] \jre\lib\ext"中。其中[jre directory]是指JRE默认安装路径。
2.2 配置NetBean平台
在netbean平台中,将Jpcap\lib\压缩包中的jpcap.jar添加到项目库中。鼠标右击项目“库”->“添加jar”。
运行capturedialog.java程序,能看到参数设置对话框,说明所有的安装和环境配置成功。
import java.awt.event.ActionListener;
import jpcap.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Jcapturedialog extends javax.swing.JDialog implements ActionListener {
static JpcapCaptor jpcap = null;
private JRadioButton wholeRadioButton;
private JPanel buttonPanel;
private JButton cancelButton;
private JButton okButton;
private JRadioButton userRadioButton;
private JRadioButton headRadioButton;
private JPanel netPanel;
private JTextField caplenTextField;
private JPanel caplenPanel;
private JTextField TextField;
private JPanel filterPanel;
private JCheckBox CheckBox;
private JComboBox netJComboBox;
private JPanel jPanel_east;
private JPanel jPanel_west;
NetworkInterface[] devices;
public static void main(String[] args) {
JFrame frame = new JFrame();
Jcapturedialog inst = new Jcapturedialog(frame);
inst.setVisible(true);
if(!inst.isVisible())
System.exit(0);
}
public Jcapturedialog(JFrame frame) {
super(frame, "选择要检测的网卡并设置参数", true);
try {
BoxLayout thisLayout = new BoxLayout(
getContentPane(),
javax.swing.BoxLayout.X_AXIS);
getContentPane().setLayout(thisLayout);
{
jPanel_west = new JPanel();
jPanel_west.setLayout(new BoxLayout(jPanel_west, BoxLayout.Y_AXIS));
getContentPane().add(jPanel_west);
{
netPanel = new JPanel();
FlowLayout netPanelLayout = new FlowLayout();
netPanelLayout.setAlignOnBaseline(true);
netPanel.setBorder(BorderFactory.createTitledBorder("选择网卡"));
netPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
jPanel_west.add(netPanel);
netPanel.setLayout(netPanelLayout);
{
devices = JpcapCaptor.getDeviceList();
if (devices == null) {
JOptionPane.showMessageDialog(frame, "没有找到网卡");
dispose();
return;
} else {
String[] names = new String[devices.length];
for (int i = 0; i < names.length; i++) {
names[i] = (devices[i].description == null ? devices[i].name : devices[i].description);
}
netJComboBox = new JComboBox(names);
}
netPanel.add(netJComboBox);
}
}
{
CheckBox = new JCheckBox();
jPanel_west.add(CheckBox);
FlowLayout CheckBoxLayout = new FlowLayout();
CheckBoxLayout.setAlignOnBaseline(true);
CheckBox.setText("是否设置为混杂模式");
CheckBox.setLayout(null);
}
{
filterPanel = new JPanel();
filterPanel.setBorder(BorderFactory.createTitledBorder("捕获过滤器"));
filterPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
FlowLayout filterPanelLayout = new FlowLayout();
filterPanelLayout.setAlignment(FlowLayout.LEFT);
filterPanelLayout.setAlignOnBaseline(true);
jPanel_west.add(filterPanel);
filterPanel.setLayout(filterPanelLayout);
{
TextField = new JTextField(20);
filterPanel.add(TextField);
}
}
}
{
jPanel_east = new JPanel();
jPanel_east.setLayout(new BoxLayout(jPanel_east, BoxLayout.Y_AXIS));
getContentPane().add(jPanel_east);
{
caplenPanel = new JPanel();
caplenPanel.setBorder(BorderFactory.createTitledBorder("最长字长"));
caplenPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
jPanel_east.add(caplenPanel);
caplenPanel.setLayout(new BoxLayout(caplenPanel, BoxLayout.Y_AXIS));
{
caplenTextField = new JTextField(20);
caplenPanel.add(caplenTextField);
caplenTextField.setText("1514");
caplenTextField.setEnabled(false);
}
{
wholeRadioButton = new JRadioButton();
FlowLayout userRadioButtonLayout = new FlowLayout();
userRadioButtonLayout.setAlignOnBaseline(true);
caplenPanel.add(wholeRadioButton);
wholeRadioButton.setText("整个数据报");
wholeRadioButton.setSelected(true);
wholeRadioButton.addActionListener(this);
}
{
headRadioButton = new JRadioButton();
caplenPanel.add(headRadioButton);
headRadioButton.setText("仅首部");
headRadioButton.addActionListener(this);
}
{
userRadioButton = new JRadioButton();
caplenPanel.add(userRadioButton);
userRadioButton.setText("其他部分");
userRadioButton.addActionListener(this);
}
ButtonGroup group = new ButtonGroup();
group.add(wholeRadioButton);
wholeRadioButton.setActionCommand("Whole");
group.add(headRadioButton);
headRadioButton.setActionCommand("Head");
group.add(userRadioButton);
userRadioButton.setActionCommand("user");
}
{
buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
jPanel_east.add(buttonPanel);
{
okButton = new JButton();
buttonPanel.add(okButton);
FlowLayout cancelButtonLayout = new FlowLayout();
cancelButtonLayout.setAlignOnBaseline(true);
okButton.setText("确定");
okButton.setActionCommand("ok");
okButton.addActionListener(this);
}
{
cancelButton = new JButton();
buttonPanel.add(cancelButton);
cancelButton.setText("取消");
cancelButton.setActionCommand("cancel");
cancelButton.addActionListener(this);
}
}
}
getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.X_AXIS));
getContentPane().add(jPanel_west);
getContentPane().add(jPanel_east);
pack();
} catch (Exception e) {
e.printStackTrace();
}
}
public void actionPerformed(ActionEvent evt) {
String cmd = evt.getActionCommand();
if (cmd.equals("Whole")) {
caplenTextField.setText("1514");
caplenTextField.setEnabled(false);
} else if (cmd.equals("Head")) {
caplenTextField.setText("68");
caplenTextField.setEnabled(false);
} else if (cmd.equals("user")) {
caplenTextField.setText("");
caplenTextField.setEnabled(true);
caplenTextField.requestFocus();
} else if (cmd.equals("ok")) {
try {
int caplen = Integer.parseInt(caplenTextField.getText());
if (caplen < 68 || caplen > 1514) {
JOptionPane.showMessageDialog(null, "捕获长度必须介于68和1514之间");
return;
}
jpcap = JpcapCaptor.openDevice(devices[netJComboBox.getSelectedIndex()], caplen,
CheckBox.isSelected(), 10);
if (TextField.getText() != null && TextField.getText().length() > 0) {
jpcap.setFilter(TextField.getText(), true);
}
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(null, "捕获长度必须是正整数");
} catch (java.io.IOException e) {
JOptionPane.showMessageDialog(null, e.toString());
jpcap = null;
} finally {
dispose();
}
} else if (cmd.equals("cancel")) {
dispose();
}
}
public static JpcapCaptor getJpcap(JFrame parent) {
new Jcapturedialog(parent).setVisible(true);
return jpcap;
}
}
注意F&Q:
上述工作完成后,运行程序Jcapturedialog.java,若运行不正常,查找是否出现下列问题:
(1) 若错误提示是“no dependence libray”, WinPcap没有安装或未装好, 重装WinPcap;
(2)如果出现”no Jpcap in …java library.path”或“no ipcap.dll in jdk/bin……”等原因是没有正确安装好Ppcap软件。解决的办法是:再次运行Jpacp安装软件,若问题未解决,查看所有的java/bin下是否有Jpcap.dll, 所有的java/lib/ext下是否有Jpcap.jar, 若没有手动复制进去。
(3)Jcapturedialog.java程序存在的问题:若存在devices变量兼容性问题,去掉import java.net. NetworkInterface[]。
(4)若出现“不是有效的Win32应用程序”,可能是WinPcap的版本问题,应下载一个64/32位兼容的版本。
3 程序设计第二步:抓包程序设计
制作如图所示的网络抓包主程序对话框,可命名为:NetcaptureJFrame.java
具体代码:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package Chapter10;
import jpcap.*;
import jpcap.packet.Packet;
public class NetcaptureJFrame extends javax.swing.JFrame {
PacketReceiver packetHandler;
boolean captureFlag=true;
/**
* Creates new form Jcapturedialog
*/
public NetcaptureJFrame() {
initComponents();
packetHandler = new PacketReceiver()
{
//实现接口中的抽象方法receivePacket()
public void receivePacket(Packet packet)
{
String msg = packet.toString();
// System.out.println(msg);
//只显示和某IP地址有关的包信息
//if(msg.contains("192.168.43.166") &&(msg.contains("8000")))
//if(msg.contains("8000"))
//if(msg.contains("10.211.55") )
if(msg.contains("202.116.192") ) //这里202.116.192是的IP地址的前面三个部分
{
System.out.println(msg);
jTextArea1.append(msg + "\n");
// String submsg = new String(packet.data,0,packet.data.length,"utf-8");
//进一步查看包中的数据部分
try
{
String submsg = new String(packet.data,0,packet.data.length,"utf-8");
//显示这类包中含某些关键词的包数据
String keyWords = ""; //定义你想要查看的关键字信息
// String keyWords1 = "8000";
if(submsg.contains(keyWords))//&&submsg.contains(keyWords1))
{
jTextArea1.append("数据部分:\n" + submsg + " \n\n");
}
}catch(Exception e)
{
e.printStackTrace();
}
}
}
};
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jLabel1 = new javax.swing.JLabel();
jScrollPane1 = new javax.swing.JScrollPane();
jTextArea1 = new javax.swing.JTextArea();
jButton1 = new javax.swing.JButton();
jButton2 = new javax.swing.JButton();
jButton3 = new javax.swing.JButton();
jButton4 = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jLabel1.setText("包信息:");
jTextArea1.setColumns(20);
jTextArea1.setRows(5);
jScrollPane1.setViewportView(jTextArea1);
jButton1.setText("开始");
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton1ActionPerformed(evt);
}
});
jButton2.setText("停止");
jButton2.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton2ActionPerformed(evt);
}
});
jButton3.setText("清空");
jButton3.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton3ActionPerformed(evt);
}
});
jButton4.setText("退出");
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jLabel1)
.addGap(0, 0, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup()
.addComponent(jButton1)
.addGap(18, 18, 18)
.addComponent(jButton2)
.addGap(48, 48, 48)
.addComponent(jButton3)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 106, Short.MAX_VALUE)
.addComponent(jButton4)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 236, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 43, Short.MAX_VALUE))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jButton2)
.addComponent(jButton1)
.addComponent(jButton3)
.addComponent(jButton4))
.addContainerGap())
);
pack();
}// </editor-fold>
//开始按钮
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
captureFlag = true;
try
{
//获得主机的网卡设备
NetworkInterface[] devices = JpcapCaptor.getDeviceList();
//实例化一个网络捕获器,一般用默认的第一块网卡
//第一个参数为网络接口的名字;第二个参数为一次捕获的最大字节数量;第三个参数为true,表示设置为混杂模式
//第四个参数为processPacket()的timeout事件 毫秒
JpcapCaptor jpcap = JpcapCaptor.openDevice(devices[4],1514, true, 60);
//JpcapCaptor jpcap = JpcapCaptor.openDevice(devices[0],1514, true, 60);
//在这台Thankpad笔记本上,无线网卡是第4块网卡;
//只抓TCP包
jpcap.setFilter("tcp", true);
System.out.println("开始抓包");
// Thread captureThread = null;
Thread captureThread = new Thread()
{
public void run()
{
System.out.println("抓包线程启动");
while(captureFlag == true)
{
//每次抓一个包交给packetHandler处理
jpcap.processPacket(1, packetHandler);
}
}
};
//设置线程抢先
captureThread.setPriority(Thread.MIN_PRIORITY);
captureThread.start();
}catch(Exception e)
{
e.printStackTrace();
}
}
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
captureFlag = false;
}
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
jTextArea1.setText("");
}
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(NetcaptureJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(NetcaptureJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(NetcaptureJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(NetcaptureJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new NetcaptureJFrame().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton jButton1;
private javax.swing.JButton jButton2;
private javax.swing.JButton jButton3;
private javax.swing.JButton jButton4;
private javax.swing.JLabel jLabel1;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JTextArea jTextArea1;
// End of variables declaration
}
4程序设计第三步:发包程序设计
发包是指利用Jpcap开发包中提供的JpcapSender类来发送一个或多个IP包、TCP包等特定的构造包,以实现特定的目的,如网络安全检测、网络泛洪攻击等。
下面以发送TCP包为例来介绍发送一个特定包的程序设计。此类技术可用来设计高级隐蔽的端口扫描程序,以下是发包程序的骨干语句。
(1) 获取网络接口参数:
NetworkInterface[] devices = JpcapCaptor.getDeviceList();
(2) 实例化JpcapSender类,取名sender:
JpcapSender sender=JpcapSender.openDevice(devices[0]);
//根据自己机器配置情况,取其中的某网卡,如第一个网卡.
(3) 构造一个TCP包:
TCPPacket tcp=new TCPPacket(int src_port, int dst_port, long sequence, long ack_num, boolean urg, boolean ack,boolean psh,boolean rst, boolean syn, boolean fin, boolean rsv1,boolean rsv2, int window, int urgent);
例如:tcp=new TCPPacket
(8000,80,56,78,false,false,false,false,true,false,true,true,20,10);
(4) 设置TCPIPv4头参数:
Tcp.setIPv4Parameter(0,false,false,false,0,false,false,false,0,1010101,100, IPPacket.IPPROTO_TCP, InetAddress.getByName(源IP地址), InetAddress. getByName (目的IP地址));
//源IP地址中填入自己主机的IP地址;
//目的IP地址填入包要到达的主机地址;
//建议2人一组,以对方的IP地址为目的地址。
(5) 填充TCP中的用户数据:
tcp.data=“学号和姓名”//字节型的用户数据。
(6) 构造相应的MAC头:
EthernetPacket ether=new EthernetPacket();
ether.frametype=EthernetPacket.ETHERTYPE_IP;
tcp.datalink=ether;
(7) 给MAC地址赋值:
//MAC地址要转换成十进制,ipconfig /all 查看本机的MAC地址.
//源地址是自己机器的MAC地址。
ether.src_mac=new byte[]{(byte)00,(byte)27,(byte)185,(byte)177,(byte)74,(byte)70};
//arp -a,查看默认网关(其IP一般是.1或.254的机器)的MAC地址,用默认网关作//为下一跳转发该包.
ether.dst_mac=new byte[]{(byte)00,(byte)17,(byte)93,(byte)157,(byte)128,(byte)00};
//理解什么是下一跳。
(8) 发送特定的TCP包:
sender.sendPacket(tcp);
具体代码:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package Chapter10;
import java.net.InetAddress;
import jpcap.*;
import jpcap.packet.EthernetPacket;
import jpcap.packet.IPPacket;
import jpcap.packet.TCPPacket;
public class SendPacket {
public static void main(String args[])
{
try
{
NetworkInterface[] devices = JpcapCaptor.getDeviceList();
//实例化一个发送器
JpcapSender sender = JpcapSender.openDevice(devices[0]);
//构造一个TCP包
//TCPPacket(int src_port,int dst_port, long sequence, long ack_num,boolean urg, boolean ack, boolean psh, boolean rst,
// boolean syn, boolean fin,boolean rsv1, boolean rsv2, int window, int urgent);
TCPPacket tcp = new TCPPacket(8000,80,56,78,false,false,false,false,true,false,true,true,200,10);
/* tcp.setIPv4Parameter(0, false, false, false, 0,false, false, false, 0,1010101,
100,IPPacket.IPPROTO_TCP, InetAddress.getByName("10.211.55.5"), InetAddress.getByName("202.116.192.17"));
//sourceIP destIP
*/
tcp.setIPv4Parameter(0, false, false, false, 0,false, false, false, 0,1010101,
100,IPPacket.IPPROTO_TCP, InetAddress.getByName("192.168.1.136"), InetAddress.getByName("202.116.195.***"));
//sourceIP destIP
tcp.data= "20180000121-李四".getBytes();
System.out.println(tcp.data.length);
//构造相应的MAC头部
EthernetPacket ether =new EthernetPacket();
ether.frametype = EthernetPacket.ETHERTYPE_IP;
tcp.datalink = ether;
//本机的网卡地址
// F8-59-71-7E-24-DA
ether.src_mac = new byte[]{(byte)248,(byte)89,(byte)113,(byte)126,(byte)36,(byte)218};
//局域网的网关地址 arp -a
//b0-d5-9d-af-5e-dd
//ether.dst_mac = new byte[]{(byte)00,(byte)28,(byte)66,(byte)00,(byte)00,(byte)24};
//02-1a-11-f6-f8-53
//48-f8-b3-6e-19-7a
ether.dst_mac = new byte[]{(byte)72,(byte)248,(byte)179,(byte)110,(byte)25,(byte)122};
sender.sendPacket(tcp);
System.out.println("发包成功!");
}catch(Exception e)
{
e.printStackTrace();
}
}
}
NSMutableArray *priceArray = [NSMutableArray arrayWithObjects:@"0.2",@"5",@"44",@"67",@"98.5",@"1.55", nil];[priceArray sortUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull
pm,即package manager, 还记得Android Framework层的PackageManager吗?利用PackageManager,可以访问到PackageManagerService。
如图,安装scrapy库后,敲了个e并不能自动补全extract要全手打。解决方法:File-->Settings-->Project Interpreter-->这个换成你python.exe的路径点击右上角的 + ,搜索你不能自动补全代码的第三方库(第三方库从这里安装能保证你的库是安装在你当前所运行的虚拟环境中的,pip安装的并不能保证你的安装路径和当前虚拟环境路径一致)Manage Repositories --> + --&...
一、分配更多资源性能调优的王道,就是增加和分配更多的资源,性能和速度上的提升是显而易见的,基本上,在一定范围之内,增加资源与性能的提升是成正比的。写完了一个复杂的Spark作业之后,进行性能调优的时候,首先第一步,就是要调节最优的资源配置,在这个基础之上,如果说你的Spark作业,能够分配的资源达到了你的能力范围的顶端之后,无法再分配更多的资源了,公司资源有限,那么才是考虑去做后面的这些性能调...
以下命令都是我边做项目边学习的strip命令 知道stripper 吧,哈哈。 对,strip就是将某部分内容删除。map命令 一张图搞定power 命令 可是让我好找,一直找不到,,sqrt命令 就是一个开方命令。
RPC:远程过程调用默认情况下服务器并不多线程化rpcgen -C data.x -DDEBUG -Mgcc server.c data_svc.c data_xdr.c -o servergcc client.c data_clnt.c data_xdr.c -o client
python存储mysqlA few days ago, I publishedCollecting / Storing Tweets with Python and MongoDB. In that post, I describe the steps needed to collect and store tweets gathered via the Twitter Streaming A...
一.ADC及触摸屏接口图
一、JSON概念JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。JSON数据格式示例:{ "学生": [ {"姓名":"小明","年龄":23}, {"姓名":"大憨","年龄":24} ]}复制代码一个对象以“{”(左括号)
简单说光端机是光信号传输的终端设备,光端机一般都是成对使用,分为光发射机和光接收机。市面上常见的光端机主要有:电话光端机、PDH光端机、高清视频光端机、音频光端机、以太网光端机、数据光端机等等。那么,各类光端机的作用是什么呢,接下来飞畅科技的小编给大家介绍一下各类光端机的具体作用,一起来看看吧!电话光端机的作用:电话光端机就是把传统的电话信号转换成光信号并在光纤上传输的设备。电话光端机出现了多种业务接口,如2/4线音频,2/4线E/M,部队用的磁石,RS232数据等。PDH光端机的作用:.
uClinux小型化的做法 -------------------------------------------------------------------- 标准Linux可能采用的小型化方法1. 重新编译内核Linux内核采用模块化的设计,即很多功能块可以独立的加上或卸下,开发人员在设计内核时把这些内核模块作为可选的选项,可以
Hack The Box注册 —邀请码教学(含注册失败及免费上网步骤)嫌麻烦的直接看这里详细教学看这里重头戏(无法注册解决方法)官网:https://www.hackthebox.eu邀请码填写地址:https://www.hackthebox.eu/invite注册账号时需科学online 验证google机器人验证,提前准备好推荐用手机注册,当然电脑也行(手机更快),这里用手机教学嫌麻烦的直接看这里打开官网->开发者选项(F12)->点击Console->输入$.post