【实例简介】

【实例截图】

【核心代码】

import java.net.*;

import java.util.List;

import java.awt.*;

import javax.swing.*;

import java.util.*;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.net.InetAddress;

import java.awt.event.WindowEvent;

import java.awt.event.WindowAdapter;

import java.io.*;

public class p2p {

boolean packFrame = false;

/**

* Construct and show the application.

*/

public p2p() {

MainFrame frame = new MainFrame();

// Validate frames that have preset sizes

// Pack frames that have useful preferred size info, e.g. from their layout

if (packFrame) {

frame.pack();

} else {

frame.validate();

}

// Center the window

Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();

Dimension frameSize = frame.getSize();

if (frameSize.height > screenSize.height) {

frameSize.height = screenSize.height;

}

if (frameSize.width > screenSize.width) {

frameSize.width = screenSize.width;

}

frame.setLocation((screenSize.width - frameSize.width) / 2,

(screenSize.height - frameSize.height) / 2);

frame.setVisible(true);

}

public static void main(String[] args) {

SwingUtilities.invokeLater(new Runnable() {

public void run() {

try {

UIManager.setLookAndFeel(UIManager.

getSystemLookAndFeelClassName());

} catch (Exception exception) {

exception.printStackTrace();

}

new p2p();

}

});

}

}

class MainFrame extends JFrame {

JPanel contentPane;

JButton jbtnSend = new JButton();

JButton jliaotian = new JButton();

JLabel jlblIP = new JLabel();

JLabel jlblIP1 = new JLabel();

JLabel jlblIP2 = new JLabel();

JButton jbtnSetting = new JButton();

JTabbedPane jtpTransFile = new JTabbedPane();

JTextArea help = new JTextArea(5, 20);

TransFileManager tfm=new TransFileManager(jtpTransFile);

public MainFrame() {

try {

setDefaultCloseOperation(EXIT_ON_CLOSE);

jbInit();

} catch (Exception exception) {

exception.printStackTrace();

}

}

private void jbInit() throws Exception {

contentPane = (JPanel) getContentPane();

contentPane.setLayout(null);

this.getContentPane().setBackground(new Color(206, 227, 249));

setSize(new Dimension(400, 300));

this.setResizable(false);

setTitle("P2P文件传输");

this.addWindowListener(new MainFrame_this_windowAdapter(this));

help.append("*基于局域网操作提示:\n");

help.append("1.直接在“对方IP”中填写对方软件右上角的“局域网IP”。\n");

help.append("2.在“对方端口号”中填写对方端口。\n");

help.append(" (注:端口号可在“设置”中修改)\n");

help.append("*基于Internet操作提示\n");

help.append("1.在“对方IP”中填写对方在Internet中的IP。\n");

help.append(" (注:此IP可以通过电脑上网查询,如:登陆www.ip138.com)\n");

help.append("2.在“对方端口号”中填写对方端口。\n");

help.append(" (注:端口号可在“设置”中修改)\n");

jbtnSend.setBackground(new Color(236, 247, 255));

jbtnSend.setBounds(new Rectangle(14, 4, 85, 25));

jbtnSend.setFont(new java.awt.Font("宋体", Font.PLAIN, 13));

jbtnSend.setBorder(BorderFactory.createRaisedBevelBorder());

jbtnSend.setText("发送文件");

jbtnSend.addActionListener(new MainFrame_jbtnSend_actionAdapter(this));

jbtnSetting.setBackground(new Color(236, 247, 255));

jbtnSetting.setBounds(new Rectangle(106,18,73, 25));

jbtnSetting.setFont(new java.awt.Font("宋体", Font.PLAIN, 13));

jbtnSetting.setBorder(BorderFactory.createRaisedBevelBorder());

jbtnSetting.setText("设置");

jliaotian.setBackground(new Color(236, 247, 255));

jliaotian.setBounds(new Rectangle(14, 29, 85, 25));

jliaotian.setFont(new java.awt.Font("宋体", Font.PLAIN, 13));

jliaotian.setBorder(BorderFactory.createRaisedBevelBorder());

jliaotian.setText("与TA聊天");

jliaotian.addActionListener(new java.awt.event.ActionListener() {public void actionPerformed(ActionEvent e) {new ChatFrame();}});

jbtnSetting.addActionListener(new MainFrame_jbtnSetting_actionAdapter(this));

jtpTransFile.setBackground(new Color(206, 227, 249));

jtpTransFile.setBounds(new Rectangle( 0, 54, 402, 246));

jlblIP.setFont(new java.awt.Font("宋体", Font.PLAIN, 13));

jlblIP.setBounds(new Rectangle(197, 5, 180, 16));

jlblIP1.setFont(new java.awt.Font("宋体", Font.PLAIN, 13));

jlblIP1.setBounds(new Rectangle(197, 21, 250, 16));

jlblIP1.setText("在Internet上的IP请上网查询");

jlblIP2.setFont(new java.awt.Font("宋体", Font.PLAIN, 13));

jlblIP2.setBounds(new Rectangle(197, 36, 250, 16));

jlblIP2.setText("(如:www.ip138.com)");

contentPane.setBackground(new Color(206, 227, 249));

jtpTransFile.add(help,"帮助");

contentPane.setToolTipText("");

contentPane.add(jtpTransFile);

contentPane.add(jbtnSend);

contentPane.add(jbtnSetting);

contentPane.add(jliaotian);

contentPane.add(jlblIP);

contentPane.add(jlblIP1);

contentPane.add(jlblIP2);

byte [] ip=InetAddress.getLocalHost().getAddress();

jlblIP.setText("局域网IP:" (ip[0]&0xff) "." (ip[1]&0xff) "." (ip[2]&0xff) "." (ip[3]&0xff));

tfm.start();

}

public void jbtnSetting_actionPerformed(ActionEvent e) {

SettingDialog sd=new SettingDialog(this);

sd.jtfPort.setText(String.valueOf(tfm.port));

sd.jspnThreadNum.setValue(new Integer(tfm.maxThreadNum));

sd.show();

if(sd.flag){

if(tfm.port!=sd.port){

tfm.setPort(sd.port);

}

tfm.setMaxThreadNum(sd.threadNum);

}

}

public void jbtnSend_actionPerformed(ActionEvent e) {

TransFileDialog tfd=new TransFileDialog(this);

tfd.show();

if(tfd.flag){

for(int i=0;i

tfm.sendFile(tfd.serverName,tfd.port,tfd.files[i].getAbsolutePath(),tfd.message);

}

}

}

public void this_windowClosed(WindowEvent e) {

tfm.close();

}

}

class MainFrame_this_windowAdapter extends WindowAdapter {

private MainFrame adaptee;

MainFrame_this_windowAdapter(MainFrame adaptee) {

this.adaptee = adaptee;

}

public void windowClosed(WindowEvent e) {

adaptee.this_windowClosed(e);

}

}

class MainFrame_jbtnSend_actionAdapter implements ActionListener {

private MainFrame adaptee;

MainFrame_jbtnSend_actionAdapter(MainFrame adaptee) {

this.adaptee = adaptee;

}

public void actionPerformed(ActionEvent e) {

adaptee.jbtnSend_actionPerformed(e);

}

}

class MainFrame_jbtnSetting_actionAdapter implements ActionListener {

private MainFrame adaptee;

MainFrame_jbtnSetting_actionAdapter(MainFrame adaptee) {

this.adaptee = adaptee;

}

public void actionPerformed(ActionEvent e) {

adaptee.jbtnSetting_actionPerformed(e);

}

}

class Server extends Thread {

public Server() {

try {

jbInit();

} catch (Exception ex) {

ex.printStackTrace();

}

}

public int port=5000;

public int maxThreadNum=5;

private ServerSocket checkServer = null;

private SocketThread socketThread = null;

private Socket aSocket = null;

private List socketPool; //socket连接池

private boolean serverRunning = false; //服务器是否运行

//构造函数

public Server(List socketPool) {

this.socketPool = socketPool;

}

public void run() {

serverRunning = true;

try {

checkServer = new ServerSocket(port);

checkServer.setSoTimeout(60000);

} catch (IOException ex) {

ex.printStackTrace();

}

while (serverRunning) {

try {

System.out.println("Started...");

aSocket = checkServer.accept();

System.out.println("client connected");

socketThread = new SocketThread(aSocket);

socketThread.start();

if(socketPool.size()>=maxThreadNum){

socketThread.stopThread();

}

else{

socketPool.add(socketThread);

}

}

catch (Exception ex) {

ex.printStackTrace();

}

try {

Thread.sleep(1000);

} catch (InterruptedException ex) {

ex.printStackTrace();

}

}

try {

checkServer.close();

} catch (IOException ex1) {

}

}

public void stopThread(){

serverRunning=false;

}

private void jbInit() throws Exception {

}

}

class SettingDialog extends JDialog {

boolean flag=false;

int threadNum;

int port;

JLabel jlblThreadNum = new JLabel();

JSpinner jspnThreadNum = new JSpinner(new SpinnerNumberModel(5,1,10,1));

JLabel jlblPort = new JLabel();

JTextField jtfPort = new JTextField();

JButton jbtnOK = new JButton();

JButton jbtnCancel = new JButton();

public SettingDialog() {

try {

jbInit();

} catch (Exception ex) {

ex.printStackTrace();

}

}

public SettingDialog(JFrame owner) {

super(owner,true);

try {

jbInit();

} catch (Exception ex) {

ex.printStackTrace();

}

}

private void jbInit() throws Exception {

jlblThreadNum.setFont(new java.awt.Font("宋体", Font.PLAIN, 12));

jlblThreadNum.setText("最大线程数");

jlblThreadNum.setBounds(new Rectangle(30, 17, 75, 21));

this.getContentPane().setLayout(null);

jspnThreadNum.setBorder(BorderFactory.createEtchedBorder());

jspnThreadNum.setBounds(new Rectangle(123, 15, 63, 22));

jbtnOK.addActionListener(new SettingDialog_jbtnOK_actionAdapter(this));

jbtnCancel.addActionListener(new SettingDialog_jbtnCancel_actionAdapter(this));

jlblPort.setFont(new java.awt.Font("宋体", Font.PLAIN, 12));

jbtnOK.setBackground(new Color(236, 247, 255));

jbtnOK.setFont(new java.awt.Font("宋体", Font.PLAIN, 12));

jbtnOK.setBorder(BorderFactory.createRaisedBevelBorder());

jbtnCancel.setBackground(new Color(236, 247, 255));

jbtnCancel.setFont(new java.awt.Font("宋体", Font.PLAIN, 12));

jbtnCancel.setBorder(BorderFactory.createRaisedBevelBorder());

jtfPort.setBackground(Color.white);

jtfPort.setBorder(BorderFactory.createEtchedBorder());

this.getContentPane().setBackground(new Color(206, 227, 249));

this.setTitle("设置");

this.getContentPane().add(jspnThreadNum, null);

jbtnCancel.setBounds(new Rectangle(213, 85, 71, 25));

jbtnCancel.setText("取消");

jbtnOK.setBounds(new Rectangle(132, 85, 71, 25));

jbtnOK.setText("确定");

jtfPort.setText("");

jtfPort.setBounds(new Rectangle(123, 52, 62, 21));

jlblPort.setText("端口号");

jlblPort.setBounds(new Rectangle(32, 50, 64, 16));

this.getContentPane().add(jlblThreadNum, null);

this.getContentPane().add(jtfPort);

this.getContentPane().add(jlblPort);

this.getContentPane().add(jbtnCancel);

this.getContentPane().add(jbtnOK);

this.setSize(300,160);

this.setLocation(300,260);

}

public void jbtnOK_actionPerformed(ActionEvent e) {

if(jtfPort.getText().trim().equals("")){

JOptionPane.showMessageDialog(this,"数据输入错误!");

return;

}

threadNum=((Integer)jspnThreadNum.getValue()).intValue();

port=Integer.parseInt(jtfPort.getText());

flag=true;

this.setVisible(false);

}

public void jbtnCancel_actionPerformed(ActionEvent e) {

this.setVisible(false);

}

}

class SettingDialog_jbtnCancel_actionAdapter implements ActionListener {

private SettingDialog adaptee;

SettingDialog_jbtnCancel_actionAdapter(SettingDialog adaptee) {

this.adaptee = adaptee;

}

public void actionPerformed(ActionEvent e) {

adaptee.jbtnCancel_actionPerformed(e);

}

}

class SettingDialog_jbtnOK_actionAdapter implements ActionListener {

private SettingDialog adaptee;

SettingDialog_jbtnOK_actionAdapter(SettingDialog adaptee) {

this.adaptee = adaptee;

}

public void actionPerformed(ActionEvent e) {

adaptee.jbtnOK_actionPerformed(e);

}

}

/**

* Socket线程

*/

class SocketThread extends Thread {

public SocketThread() {

try {

jbInit();

} catch (Exception ex) {

ex.printStackTrace();

}

}

public final static int CACHE_SIZE = 10240; //缓存大小

public final static int FILE_TRANS_STATUS_FILENAME = 0x01; //文件名传输状态

public final static int FILE_TRANS_STATUS_CONTEXT = 0x02; //文件内容传输状态

public final static int FILE_TRANS_STATUS_WAITFORCONFIRM = 0x03; //等待确认接收文件

public final static int FILE_TRANS_STATUS_SUCCESS = 0x04; //文件传输成功

public final static int FILE_TRANS_STATUS_FAIL = 0x05; //文件传输失败

public final static int FILE_TRANS_STATUS_CANCELTRANS = 0x06; //取消文件传输

public final static int PACKAGE_TYPE_FILENAME = 0x01; //文件名包

public final static int PACKAGE_TYPE_CONTEXT = 0x02; //文件内容包

public final static int PACKAGE_TYPE_CONFIRMRECEIVE = 0x03; //是否接收文件

private Socket aSocket; //套接字

private String serverName; //服务器名称

private DataInputStream dis; //输入流

private DataOutputStream dos; //输出流

private DataInputStream fDis; //文件输入流

private RandomAccessFile raf; //文件输出流

private boolean fileSender = false; //文件发送者

private boolean running = false; //线程运行

public int fileTransStatus = 0x0; //文件传输状态

private File aFile; //传输的文件

public long fileSize; //文件大小

private String fileName; //文件名称

private String errorMessage; //错误消息

private long transFileLength = 0; //已传输字节数

private byte [] dataBuf;

private String message; //验证消息

private String IP; //目标IP

private int port; //目标端口

private boolean fileTransed=false; //文件是否已经开始传输

int count=0;

//接收者构造函数

public SocketThread(Socket aSocket) {

this.aSocket = aSocket;

try {

aSocket.setSoTimeout(300000);

} catch (SocketException ex) {

}

byte[] address = aSocket.getInetAddress().getAddress();

IP = (address[0] & 0xff) "." (address[1] & 0xff) "."

(address[2] & 0xff) "." (address[3] & 0xff);

try {

dis = new DataInputStream(aSocket.getInputStream());

dos = new DataOutputStream(aSocket.getOutputStream());

fileTransStatus = FILE_TRANS_STATUS_FILENAME;

} catch (IOException ex) {

setError("创建连接错误!");

}

try {

aSocket.setReceiveBufferSize(CACHE_SIZE*2);

} catch (SocketException ex1) {

ex1.printStackTrace();

}

dataBuf=new byte[CACHE_SIZE 100];

}

//发送者构造函数

public SocketThread(String serverName, int portNo, String fileName,

String message) {

aFile = new File(fileName);

this.fileName = aFile.getName();

this.fileSize = fileSize;

fileSender = true;

if (message != null) {

this.message = message;

}

this.IP = serverName;

this.port = portNo;

dataBuf=new byte[CACHE_SIZE];

}

//线程执行函数

public void run() {

running = true;

if (fileSender) {

try {

aSocket = new Socket(IP, port);

aSocket.setSoTimeout(300000);

aSocket.setSendBufferSize(CACHE_SIZE*2);

dos = new DataOutputStream(aSocket.getOutputStream());

dis = new DataInputStream(aSocket.getInputStream());

fDis = new DataInputStream(new FileInputStream(aFile));

fileTransStatus = FILE_TRANS_STATUS_FILENAME;

} catch (UnknownHostException ex1) {

ex1.printStackTrace();

setError("连接服务器错误!");

} catch (IOException ex1) {

ex1.printStackTrace();

setError("创建连接错误!");

}

} while (running) {

if (fileSender) {

sendFile();

} else {

receiveFile();

}

try {

Thread.sleep(6);

} catch (InterruptedException ex) {

}

}

}

//从socket读

private int readFromSocket(byte[] data) throws IOException {

int length = 0;

length = fDis.read(data);

return length;

}

//从socket读

private int readFromSocket() throws IOException {

int buf = 0;

buf = dis.readInt();

return buf;

}

//从文件读

private int readFromFile(byte[] data,int off,int length) {

int len=0;

try {

len = fDis.read(data,off,length);

} catch (IOException ex) {

setError("文件读取错误!");

}

return len;

}

//写入socket

private void writeToSocket(byte[] data) throws IOException {

dos.write(data);

}

//写入文件

private void writeToFile(byte[] data,int off,int length) throws IOException {

raf.write(data,off,length);

}

//写入socket

private void writeToSocket(int data) throws IOException {

dos.writeInt(data);

}

private void writeToSocket(long data) throws IOException {

dos.writeLong(data);

}

private long readLongFromSocket() throws IOException {

return dis.readLong();

}

//打包

private byte[] doPackage(byte[] data, int length) throws IOException {

ByteArrayOutputStream buf = new ByteArrayOutputStream();

ByteArrayOutputStream baos = new ByteArrayOutputStream();

DataOutputStream bufDos = new DataOutputStream(buf);

DataOutputStream baosDos = new DataOutputStream(baos);

switch (fileTransStatus) {

case FILE_TRANS_STATUS_FILENAME: {

bufDos.writeInt(PACKAGE_TYPE_FILENAME);

bufDos.writeInt(fileName.getBytes().length);

bufDos.write(fileName.getBytes());

bufDos.writeLong(fileSize);

if (message!=null) {

bufDos.writeInt(message.getBytes().length);

bufDos.write(message.getBytes());

} else {

bufDos.writeInt(-1);

}

baosDos.writeInt(buf.toByteArray().length);

baosDos.write(buf.toByteArray());

break;

}

case FILE_TRANS_STATUS_CONTEXT: {

bufDos.writeInt(PACKAGE_TYPE_CONTEXT);

if ((transFileLength length) >= fileSize) {

bufDos.writeInt(0);

} else {

bufDos.writeInt(1);

}

bufDos.writeInt(length);

bufDos.write(data, 0, length);

baosDos.writeInt(buf.toByteArray().length);

baosDos.write(buf.toByteArray());

break;

}

}

return baos.toByteArray();

}

//停止线程

public void stopThread() {

running = false;

try {

if (dis != null) {

dis.close();

}

if (dos != null) {

dos.close();

}

if (fDis != null) {

fDis.close();

}

if (raf != null) {

raf.close();

}

} catch (Exception ex) {

}

}

//解包

private void upPackage(byte[] data) {

ByteArrayInputStream bias = new ByteArrayInputStream(data);

DataInputStream biasDis = new DataInputStream(bias);

int type = 0;

try {

type = biasDis.readInt();

} catch (SocketTimeoutException ex) {

setError("网络超时!");

} catch (IOException ex1) {

setError("对方取消了文件传输或网络错误!");

}

switch (type) {

case PACKAGE_TYPE_FILENAME: {

try {

int length = biasDis.readInt();

bias.read(dataBuf,0,length);

fileName = new String(dataBuf,0,length);

fileSize = biasDis.readLong();

length = biasDis.readInt();

if (length !=-1) {

bias.read(dataBuf,0,length);

message = new String(dataBuf,0,length);

}

fileTransStatus = FILE_TRANS_STATUS_WAITFORCONFIRM;

} catch (SocketTimeoutException ex) {

setError("网络超时!");

} catch (IOException ex) {

setError("对方取消了文件传输或网络错误!");

}

break ;

}

case PACKAGE_TYPE_CONTEXT: {

try {

int flag = biasDis.readInt();

int length = biasDis.readInt();

bias.read(dataBuf,0,length);

writeToFile(dataBuf,0,length);

transFileLength = length;

if (flag == 0) {

fileTransStatus = FILE_TRANS_STATUS_SUCCESS;

stopThread();

}

} catch (SocketTimeoutException ex) {

setError("网络超时!");

} catch (IOException ex) {

setError("对方取消了文件传输或网络错误!");

}

break ;

}

}

}

//发送文件

private void sendFile() {

int length;

switch (fileTransStatus) {

case FILE_TRANS_STATUS_FILENAME: {

try {

byte [] buf;

fileName = aFile.getName();

fileSize = aFile.length();

buf = doPackage(null, 0);

writeToSocket(buf);

fileTransStatus = FILE_TRANS_STATUS_WAITFORCONFIRM;

} catch (IOException ex) {

setError("对方取消了文件传输或网络错误!");

}

break ;

}

case FILE_TRANS_STATUS_WAITFORCONFIRM: {

int flag;

try {

flag = readFromSocket();

if (flag == 0) {

setError("对方拒绝了文件传输!");

} else {

fileTransStatus = FILE_TRANS_STATUS_CONTEXT;

transFileLength = readLongFromSocket();

fDis.skip(transFileLength);

aSocket.setSoTimeout(30000);

}

} catch (SocketTimeoutException ex) {

setError("网络超时!");

} catch (IOException ex) {

setError("对方取消了文件传输或网络错误!");

}

break ;

}

case FILE_TRANS_STATUS_CONTEXT: {

length = readFromFile(dataBuf,0,CACHE_SIZE);

try {

writeToSocket(doPackage(dataBuf, length));

transFileLength = length;

if (transFileLength >= fileSize) {

fileTransStatus = FILE_TRANS_STATUS_SUCCESS;

Thread.sleep(1000);

stopThread();

}

} catch (IOException ex) {

setError("对方取消了文件传输或网络错误!");

} catch (InterruptedException ex1) {

}

count ;

if(count==2){

//stopThread();

}

break ;

}

}

}

//接收文件

private void receiveFile() {

if (fileTransStatus == FILE_TRANS_STATUS_CONTEXT ||

fileTransStatus == FILE_TRANS_STATUS_FILENAME) {

try {

int length = dis.readInt();

int len=dis.read(dataBuf,0,length);

while(len

len=len dis.read(dataBuf,len,length-len);

}

upPackage(dataBuf);

} catch (SocketTimeoutException ex) {

setError("网络超时!");

ex.printStackTrace();

} catch (IOException ex) {

setError("对方取消了文件传输或网络错误!");

}

} else if (fileTransStatus == FILE_TRANS_STATUS_CANCELTRANS) {

try {

doPackage(null, 0);

} catch (IOException ex1) {

}

setError("已取消文件传输!");

}

}

//确认是否接收文件

public void confirmReceiveFile(boolean flag, String fileName, long off) {

if (flag) {

try {

writeToSocket(1);

if (off >0) {

writeToSocket(off);

} else {

writeToSocket(0L);

File aFile=new File(fileName);

if(aFile.exists()){

System.out.println("*");

aFile.delete();

}

}

raf = new RandomAccessFile(fileName, "rws");

this.fileName = fileName;

fileTransStatus = FILE_TRANS_STATUS_CONTEXT;

fileTransed=true;

raf.seek(off);

} catch (FileNotFoundException ex) {

setError("创建文件错误!");

} catch (IOException ex) {

setError("对方取消了文件传输或网络错误!");

}

transFileLength = off;

} else {

try {

writeToSocket(0);

writeToSocket(0L);

} catch (IOException ex) {

setError("对方取消了文件传输或网络错误!");

}

}

}

//返回已传输字节数

public long getTransFileLength() {

return transFileLength;

}

//设置错误消息

public void setError(String errorMessage) {

fileTransStatus = FILE_TRANS_STATUS_FAIL;

this.errorMessage = errorMessage;

if (!fileSender&&fileTransed) {

File tmpFile = new File(fileName ".tmp");

try {

DataOutputStream dos = new DataOutputStream(new

FileOutputStream(

tmpFile));

dos.writeLong(transFileLength);

dos.writeLong(fileSize);

dos.close();

} catch (IOException ex) {

}

}

stopThread();

}

//返回错误消息

public String getErrorMessage() {

return errorMessage;

}

//返回传输状态

public int getStatus() {

return fileTransStatus;

}

//是否是文件发送者

public boolean isFileSender() {

return fileSender;

}

public void cancelTrans() {

if (fileTransStatus == FILE_TRANS_STATUS_WAITFORCONFIRM) {

confirmReceiveFile(false, null, 0);

}

setError("已取消文件传输!");

}

public String getMessage() {

return message;

}

public String getIP() {

return IP;

}

public int getPort() {

return port;

}

public String getFileName() {

if (fileName.length() > 10) {

return fileName.substring(0, 10) "..."

fileName.substring(fileName.lastIndexOf('.'),

fileName.length());

} else {

return fileName;

}

}

public String getFileTransMessage(){

if(fileSender){

return "文件发送 目标IP: " getIP() " 端口:" getPort();

}

else{

return "文件接收 来自: " getIP();

}

}

private void jbInit() throws Exception {

}

}

class TransFileDialog extends JDialog {

File [] files;

boolean flag=false;

String serverName;

int port;

String message;

Object [] items;

public TransFileDialog(JFrame owner) {

super(owner,true);

this.items=items;

try {

jbInit();

} catch (Exception ex) {

ex.printStackTrace();

}

}

private void jbInit() throws Exception {

jlblServerName.setFont(new java.awt.Font("宋体", Font.PLAIN, 12));

jlblServerName.setText("对方IP");

jlblServerName.setBounds(new Rectangle(32, 22, 73, 26));

this.getContentPane().setLayout(null);

jbtnCancel.setBackground(new Color(236, 247, 255));

jbtnCancel.setBounds(new Rectangle(294, 213, 71, 25));

jbtnCancel.setFont(new java.awt.Font("宋体", Font.PLAIN, 12));

jbtnCancel.setBorder(BorderFactory.createRaisedBevelBorder());

jbtnCancel.setText("取消");

jbtnCancel.addActionListener(new TransFileDialog_jbtnCancel_actionAdapter(this));

jbtnOK.setBackground(new Color(236, 247, 255));

jbtnOK.setBounds(new Rectangle(195, 214, 71, 25));

jbtnOK.setFont(new java.awt.Font("宋体", Font.PLAIN, 12));

jbtnOK.setBorder(BorderFactory.createRaisedBevelBorder());

jbtnOK.setText("确定");

jbtnOK.addActionListener(new TransFileDialog_jbtnOK_actionAdapter(this));

jbtnFile.setBackground(new Color(236, 247, 255));

jbtnFile.setBounds(new Rectangle(297, 116, 71, 25));

jbtnFile.setFont(new java.awt.Font("宋体", Font.PLAIN, 12));

jbtnFile.setBorder(BorderFactory.createRaisedBevelBorder());

jbtnFile.setText("浏览");

jbtnFile.addActionListener(new TransFileDialog_jbtnFile_actionAdapter(this));

jtfFile.setBackground(Color.white);

jtfFile.setBorder(BorderFactory.createEtchedBorder());

jtfFile.setText("");

jtfFile.setBounds(new Rectangle(127, 118, 164, 21));

jlblFile.setFont(new java.awt.Font("宋体", Font.PLAIN, 12));

jlblFile.setText("文件");

jlblFile.setBounds(new Rectangle(32, 120, 34, 16));

jtfPort.setBackground(Color.white);

jtfPort.setBorder(BorderFactory.createEtchedBorder());

jtfPort.setText("5000");

jtfPort.setBounds(new Rectangle(129, 72, 62, 21));

jlblPort.setFont(new java.awt.Font("宋体", Font.PLAIN, 12));

jlblPort.setText("对方端口号");

jlblPort.setBounds(new Rectangle(32, 67, 67, 31));

jtfServerName.setBackground(Color.white);

jtfServerName.setBorder(BorderFactory.createEtchedBorder());

this.getContentPane().setBackground(new Color(206, 227, 249));

this.setTitle("发送文件");

jlblMessage.setFont(new java.awt.Font("宋体", Font.PLAIN, 12));

jlblMessage.setText("简短附言");

jlblMessage.setBounds(new Rectangle(32, 169, 75, 25));

jtfMessage.setBackground(Color.white);

jtfMessage.setBorder(BorderFactory.createEtchedBorder());

jtfMessage.setText("");

jtfMessage.setBounds(new Rectangle(126, 169, 225, 29));

this.getContentPane().add(jtfServerName);

this.getContentPane().add(jtfPort);

this.getContentPane().add(jlblFile);

this.getContentPane().add(jlblServerName, null);

this.getContentPane().add(jtfFile);

this.getContentPane().add(jbtnFile);

this.getContentPane().add(jlblPort);

this.getContentPane().add(jbtnCancel);

this.getContentPane().add(jbtnOK);

this.getContentPane().add(jlblMessage);

this.getContentPane().add(jtfMessage);

jtfServerName.setText("");

jtfServerName.setBounds(new Rectangle(127, 25, 220, 21));

this.setSize(400,300);

this.setLocation(300,300);

}

JLabel jlblServerName = new JLabel();

JTextField jtfServerName = new JTextField();

JLabel jlblPort = new JLabel();

JTextField jtfPort = new JTextField();

JLabel jlblFile = new JLabel();

JTextField jtfFile = new JTextField();

JButton jbtnFile = new JButton();

JButton jbtnOK = new JButton();

JButton jbtnCancel = new JButton();

JLabel jlblMessage = new JLabel();

JTextField jtfMessage = new JTextField();

public void jbtnFile_actionPerformed(ActionEvent e) {

JFileChooser jfc=new JFileChooser();

jfc.setMultiSelectionEnabled(true);

String fileName="";

jfc.showOpenDialog(this);

files=jfc.getSelectedFiles();

for(int i=0;i

fileName=fileName files[i].getAbsolutePath() ";";

}

jtfFile.setText(fileName);

}

public void jbtnOK_actionPerformed(ActionEvent e) {

if(jtfServerName.getText().trim().equals("")||jtfPort.getText().trim().equals("")||jtfFile.getText().trim().equals("")){

JOptionPane.showMessageDialog(this,"数据填写错误!");

return;

}

serverName=jtfServerName.getText();

port=Integer.parseInt(jtfPort.getText());

message=jtfMessage.getText();

flag=true;

this.setVisible(false);

}

public void jbtnCancel_actionPerformed(ActionEvent e) {

this.setVisible(false);

}

}

class TransFileDialog_jbtnCancel_actionAdapter implements ActionListener {

private TransFileDialog adaptee;

TransFileDialog_jbtnCancel_actionAdapter(TransFileDialog adaptee) {

this.adaptee = adaptee;

}

public void actionPerformed(ActionEvent e) {

adaptee.jbtnCancel_actionPerformed(e);

}

}

class TransFileDialog_jbtnOK_actionAdapter implements ActionListener {

private TransFileDialog adaptee;

TransFileDialog_jbtnOK_actionAdapter(TransFileDialog adaptee) {

this.adaptee = adaptee;

}

public void actionPerformed(ActionEvent e) {

adaptee.jbtnOK_actionPerformed(e);

}

}

class TransFileDialog_jbtnFile_actionAdapter implements ActionListener {

private TransFileDialog adaptee;

TransFileDialog_jbtnFile_actionAdapter(TransFileDialog adaptee) {

this.adaptee = adaptee;

}

public void actionPerformed(ActionEvent e) {

adaptee.jbtnFile_actionPerformed(e);

}

}

class TransFileManager extends Thread {

public TransFileManager() {

try {

jbInit();

} catch (Exception ex) {

ex.printStackTrace();

}

}

private JTabbedPane jtp;

private boolean running = false;

private ArrayList paneList = new ArrayList();

private ArrayList threadList = new ArrayList();

private Server s;

int maxThreadNum = 5;

int port=5000;

//构造函数

public TransFileManager(JTabbedPane jtp) {

this.jtp = jtp;

s = new Server(threadList);

SocketThread st;

s.start();

}

public void run() {

running = true;

SocketThread st;

TransFilePanel tfp;

int threadListSize;

int paneListSize;

while (running) {

threadListSize = threadList.size();

paneListSize = paneList.size();

for (int i = 0; i < threadListSize; i ) {

st = (SocketThread) threadList.get(i);

if (paneListSize <= i) {

try {

Thread.sleep(100);

} catch (InterruptedException ex2) {

}

tfp = new TransFilePanel(st.isFileSender());

jtp.addTab(st.getFileName(), tfp);

paneList.add(tfp);

tfp.jtaFileTransStatus.setText("文件发送 目标IP:" st.getIP() " 端口:" st.getPort() "\n\n正在与对方建立连接...");

} else {

tfp = (TransFilePanel) paneList.get(i);

}

tfp.setStatus(st.getStatus());

if (tfp.isCanneled) {

st.cancelTrans();

}

switch (st.getStatus()) {

case SocketThread.FILE_TRANS_STATUS_WAITFORCONFIRM: {

if (st.isFileSender()) {

tfp.jtaFileTransStatus.setText(st.getFileTransMessage() "\n\n连接成功! 等待对方回应...");

} else {

tfp.jtaFileTransStatus.setText(st.getFileName() " ("

st.fileSize " B) 是否接收?\n" "来自:" st.getIP() "\n简短附言:" st.getMessage());

}

if (tfp.isConfirm) {

if(tfp.fileName!=null){

File aFile = new File(tfp.fileName);

long off=0,size;

if (aFile.exists()) {

File temFile=new File(aFile.getAbsolutePath() ".tmp");

if(temFile!=null){

try {

DataInputStream dis=new DataInputStream(new

FileInputStream(temFile));

off = dis.readLong();

System.out.println(off);

size=dis.readLong();

if(off!=new File(tfp.fileName).length()||size!=st.fileSize){

off=0;

}

} catch (IOException ex1) {

off=0;

}

}

}

st.confirmReceiveFile(true,tfp.fileName,off);

}

else{

st.confirmReceiveFile(false,"",0);

}

}

break;

}

case SocketThread.FILE_TRANS_STATUS_CONTEXT: {

double progress = st.getTransFileLength() * 1.0 /

st.fileSize * 100;

double transSpeed = (st.getTransFileLength() -

tfp.transFileLength) / 1024 * 2;

tfp.transFileLength = st.getTransFileLength();

tfp.jpgbFileTrans.setValue((int) progress);

tfp.jtaFileTransStatus.setText(st.getFileTransMessage() "\n\n");

tfp.jtaFileTransStatus.setText(tfp.jtaFileTransStatus.getText() "传输速度:" (int) transSpeed "k/s" " 已完成:" (int) progress

"%");

break;

}

case SocketThread.FILE_TRANS_STATUS_SUCCESS: {

tfp.jtaFileTransStatus.setText(st.getFileTransMessage() "\n\n传输成功!");

if(!st.isFileSender()){

new File(tfp.fileName ".tmp").delete();

}

if (tfp.isClosed) {

threadList.remove(i);

paneList.remove(i);

jtp.remove(i);

i--;

threadListSize--;

paneListSize--;

}

break;

}

case SocketThread.FILE_TRANS_STATUS_FAIL: {

tfp.jtaFileTransStatus.setText(st.getFileTransMessage() "\n\n传输失败!" st.getErrorMessage());

if (tfp.isClosed) {

threadList.remove(i);

paneList.remove(i);

jtp.remove(i);

i--;

threadListSize--;

paneListSize--;

}

break;

}

}

}

try {

Thread.sleep(500);

} catch (InterruptedException ex) {

}

}

}

public void sendFile(String serverName, int port, String fileName,String message) {

if (threadList.size() < maxThreadNum) {

SocketThread st = new SocketThread(serverName, port, fileName,message);

st.start();

threadList.add(st);

}

}

public void setPort(int port) {

s.stopThread();

s = new Server(threadList);

s.port = port;

this.port=port;

s.start();

}

public void setMaxThreadNum(int num) {

this.maxThreadNum = num;

s.maxThreadNum=num;

}

public void close(){

s.stopThread();

SocketThread st;

for(int i=0;i

st=(SocketThread)threadList.get(i);

st.stopThread();

}

}

private void jbInit() throws Exception {

}

}

class TransFilePanel extends JPanel {

int status;

boolean fileSender = false;

boolean isClosed = false;

String fileName;

boolean isConfirm = false;

boolean isCanneled=false;

long transFileLength=0;

JProgressBar jpgbFileTrans = new JProgressBar();

JButton jbtnOK = new JButton();

JButton jbtnCannel = new JButton();

JTextArea jtaFileTransStatus = new JTextArea();

public TransFilePanel(boolean fileSender) {

this.fileSender = fileSender;

try {

jbInit();

} catch (Exception ex) {

ex.printStackTrace();

}

}

private void jbInit() throws Exception {

this.setLayout(null);

jpgbFileTrans.setBounds(new Rectangle(19, 104, 209, 18));

jbtnOK.setBackground(new Color(236, 247, 255));

jbtnOK.setBounds(new Rectangle(233, 101, 67, 25));

jbtnOK.setText("接收");

jbtnOK.addActionListener(new TransFilePanel_jbtnOK_actionAdapter(this));

jbtnCannel.setBackground(new Color(236, 247, 255));

jbtnCannel.setBounds(new Rectangle(306, 101, 67, 25));

jbtnCannel.setText("取消");

jbtnCannel.addActionListener(new

TransFilePanel_jbtnCannel_actionAdapter(this));

this.setBackground(new Color(206, 227, 249));

this.setBorder(BorderFactory.createEtchedBorder());

jtaFileTransStatus.setBackground(new Color(206, 227, 249));

jtaFileTransStatus.setDisabledTextColor(Color.orange);

jtaFileTransStatus.setText("");

jtaFileTransStatus.setWrapStyleWord(true);

jtaFileTransStatus.setBounds(new Rectangle(20, 33, 345, 55));

this.add(jpgbFileTrans);

this.add(jbtnOK);

this.add(jbtnCannel);

this.add(jtaFileTransStatus);

jpgbFileTrans.setVisible(false);

jbtnOK.setVisible(false);

}

public void setStatus(int status) {

this.status = status;

switch (status) {

case SocketThread.FILE_TRANS_STATUS_FILENAME: {

jbtnOK.setVisible(false);

jbtnCannel.setVisible(false);

break;

}

case SocketThread.FILE_TRANS_STATUS_WAITFORCONFIRM: {

if (fileSender) {

jbtnOK.setVisible(false);

jbtnCannel.setVisible(true);

jpgbFileTrans.setVisible(false);

} else {

jbtnOK.setVisible(true);

jbtnCannel.setVisible(true);

jpgbFileTrans.setVisible(false);

}

break;

}

case SocketThread.FILE_TRANS_STATUS_CONTEXT: {

jbtnOK.setVisible(false);

jbtnCannel.setVisible(true);

jpgbFileTrans.setVisible(true);

break;

}

case SocketThread.FILE_TRANS_STATUS_SUCCESS:

case SocketThread.FILE_TRANS_STATUS_FAIL: {

jbtnCannel.setText("关闭");

jbtnOK.setVisible(false);

jbtnCannel.setVisible(true);

jpgbFileTrans.setVisible(false);

break;

}

}

}

public int getStatus() {

return status;

}

public void jbtnOK_actionPerformed(ActionEvent e) {

JFileChooser jfc = new JFileChooser();

File aFile;

jfc.showSaveDialog(this);

aFile = jfc.getSelectedFile();

if (aFile != null) {

fileName = jfc.getSelectedFile().getAbsolutePath();

isConfirm = true;

}

}

public void jbtnCannel_actionPerformed(ActionEvent e) {

if(jbtnCannel.getText().equals("取消")){

isCanneled=true;

}

else{

isClosed=true;

}

}

}

class TransFilePanel_jbtnCannel_actionAdapter implements ActionListener {

private TransFilePanel adaptee;

TransFilePanel_jbtnCannel_actionAdapter(TransFilePanel adaptee) {

this.adaptee = adaptee;

}

public void actionPerformed(ActionEvent e) {

adaptee.jbtnCannel_actionPerformed(e);

}

}

class TransFilePanel_jbtnOK_actionAdapter implements ActionListener {

private TransFilePanel adaptee;

TransFilePanel_jbtnOK_actionAdapter(TransFilePanel adaptee) {

this.adaptee = adaptee;

}

public void actionPerformed(ActionEvent e) {

adaptee.jbtnOK_actionPerformed(e);

}

}

//聊天代码开始

class ChatFrame extends JFrame {

JFrame frame;

JLabel label2 = new JLabel();//输入ip

JLabel label3 = new JLabel();//输入端口标签

JLabel label4 = new JLabel();//输出端口标签

JTextField textField1 = new JTextField();//发送消息

JTextField textField2 = new JTextField();//输入ip

JTextField textField3 = new JTextField();//获得输入端口

JTextField textField4 = new JTextField();//获得输出端口

JButton button1 = new JButton("发送");//发送消息

JButton button2 = new JButton("连接");//建立连接

TextArea textArea1 = new TextArea("信息显示:",5,15);

JOptionPane jopane = new JOptionPane();

JLabel jlabel1 = new JLabel("连接失败,请重试.");

JLabel jlabel2 = new JLabel("连接成功!");

JLabel jlabel3 = new JLabel("输入端口号和IP.");

JLabel jlabel4 = new JLabel("请先建立连接!");

JLabel jlabel5 = new JLabel("使用默认端口和IP建立连接...");

boolean link = false;

boolean online = false;

int portIn = 3001;//输入端口

int portOut = 3000;//输出端口

DatagramPacket sendpacket,receivepacket;//声明发送和接收数据包

DatagramSocket sendsocket,receivesocket;//声明发送和接收DatagramSocket

public ChatFrame() {

enableEvents(AWTEvent.WINDOW_EVENT_MASK);

try {

toInit();

}

catch(Exception e) {

e.printStackTrace();

}

}

private void toInit() throws Exception {

frame = new JFrame("与TA聊天");

Container contentPane = frame.getContentPane();

contentPane.setLayout(null);

contentPane.setBackground(new Color(206, 227, 249));

frame.setSize(365, 280);

label2.setText("输入对方IP地址:");

label2.setBounds(new Rectangle(12,19,109,23));

label3.setText("我的端口:");

label3.setBounds(new Rectangle(12,58,60,22));

label4.setText("対方端口:");

label4.setBounds(new Rectangle(180,58,60,22));

textField3.setText("3001");

textField4.setText("3000");

button1.setBounds(new Rectangle(270,210,65,21));

button1.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(ActionEvent e) {

button1_actionPerformed(e);

}

});

button2.setBounds(new Rectangle(265,20,65,21));

button2.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(ActionEvent e) {

button2_actionPerformed(e);

}

});

textField4.setBounds(new Rectangle(245,58,90,22));

textField3.setBounds(new Rectangle(75,58,90,22));

textField2.setBounds(new Rectangle(123,20,120,19));

textField1.setBounds(new Rectangle(10,211,250,19));

textArea1.setBounds(new Rectangle(11,100,323,100));

textArea1.setEditable(false);

textArea1.setBackground(Color.white);

contentPane.add(label4, null);

contentPane.add(label3, null);

contentPane.add(label2, null);

contentPane.add(textField1, null);

contentPane.add(textField2, null);

contentPane.add(textField3, null);

contentPane.add(textField4, null);

contentPane.add(textArea1, null);

contentPane.add(button1, null);

contentPane.add(button2,null);

contentPane.setVisible(true);

frame.setVisible(true);

try {

sendsocket=new DatagramSocket(3000);//实例化DatagramSocket类作为输出端

receivesocket=new DatagramSocket(3001);//实例化DatagramSocket类作为输入端

online = !(sendsocket.isClosed());

}

catch(SocketException se){//异常捕获

se.printStackTrace();

System.exit(0);

}

}

protected void processWindowEvent(WindowEvent e) {

super.processWindowEvent(e);

if(e.getID() == WindowEvent.WINDOW_CLOSING) {///

frame.setDefaultCloseOperation((JFrame.DISPOSE_ON_CLOSE));

//frame.setVisible(false);

}

}

public void waitforpackets(){//检测并接受对方发来的消息

while(true){

try {

byte[]array=new byte[100];

receivepacket=new DatagramPacket(array,array.length);

receivesocket.receive(receivepacket);//接收

//textArea1.append("\nfrom " receivepacket.getAddress() ":" receivepacket.getPort() " get:");

textArea1.append("\n" "对方说:" " get:");

String received =new String(receivepacket.getData(),0,receivepacket.getLength(),"UTF-8");

textArea1.append(received);

}

catch(IOException se) {

se.printStackTrace();

}

}

}

void button2_actionPerformed(ActionEvent e){//和对方建立连接

String str2 = new String();

String str3 = new String();

str2 = textField3.getText();

str3 = textField4.getText();

String str4 = new String();

str4 = textField2.getText();

if(str2.compareTo("")!=0&&str3.compareTo("")!=0&&str4.compareTo("")!=0){

portIn = (int)Integer.parseInt(str2);

portOut = (int)Integer.parseInt(str3);

if(online){

sendsocket.close();

receivesocket.close();

}

try {

sendsocket=new DatagramSocket(portOut);

receivesocket=new DatagramSocket(portIn);

jopane.showMessageDialog(null,jlabel2,"系统提醒",JOptionPane.OK_OPTION);

link = true;

}

catch(SocketException se){

se.printStackTrace();

System.exit(0);

}

online = !(sendsocket.isClosed());

}

else jopane.showMessageDialog(null,jlabel3,"系统提醒",JOptionPane.OK_OPTION);

}

void button1_actionPerformed(ActionEvent e) {//发送消息到对方

String str=textField2.getText();

if(online && link){

if(str.compareTo("")!=0 ){

try {

textArea1.append("\n" " 你说: " textField1.getText());

String s=textField1.getText();

byte data[]= s.getBytes("UTF-8");

sendpacket = new DatagramPacket(data,data.length,InetAddress.getByName(textField2.getText()),portOut);

sendsocket.send(sendpacket);

}

catch(IOException exc){

exc.printStackTrace();

}

textField1.setText("");

}

}

else

jopane.showMessageDialog(null,jlabel4,"系统提醒",JOptionPane.OK_OPTION);

}

}

//聊天代码结束

java p2p 下载_java p2p文件传输(含服务器端与jsp源码)相关推荐

  1. java贪吃蛇游戏代码下载_java实现贪吃蛇游戏代码(附完整源码)

    免费资源网,https://freexyz.cn/ 先给大家分享源码,喜欢的朋友点此处下载. 游戏界面 GUI界面 java实现贪吃蛇游戏需要创建一个桌面窗口出来,此时就需要使用java中的swing ...

  2. java treeset原理_Java集合 --- TreeSet底层实现和原理(源码解析)

    概述 文章的内容基于JDK1.7进行分析,之所以选用这个版本,是因为1.8的有些类做了改动,增加了阅读的难度,虽然是1.7,但是对于1.8做了重大改动的内容,文章也会进行说明. TreeSet实现了S ...

  3. java pv实现_java实现UV.PV.IP统计的实现源码包

    [实例简介] 统计网址的pv,uv,java如何实现数据统计,网站统计源码工程包 [实例截图] [核心代码] statistic └── statistic ├── src │   ├── appli ...

  4. java文件分割合并_java实现文件分割与合并 类示例源码

    [实例简介] [实例截图] [核心代码] package cn.part.com; import java.io.BufferedInputStream; import java.io.Buffere ...

  5. java股票数据_java抓取东方财富股票数据(附源码)

    背景 前段时间给朋友写了一个自动抓取同花顺股票数据的程序,不少人觉得不错. 这几天后台有粉丝给我留言让我也抓一下东方财富的数据,说东方财富的数据特别难抓,我还真不一定能搞得定. 本来我是一个德艺双磬且 ...

  6. java图书馆管理项目_java项目实战之图书馆管理系统(带源码和解析)

    开发背景 图书馆是吉林省一家私营的中型图书馆企业.图书馆本着以读者为上帝为读者节省每一分钱的服务宗旨,企业利润逐年提高,规模不断壮大,经营图书品种.数量也逐渐增多.在企业不断发展的同时,企业传统的人工 ...

  7. java中acquire()_Java高并发系列之AQS中acquire源码解析

    我们知道,AQS中最重要的两个方法就是acquire和release方法.我们本文来走读走读acquire的源码. 首先,tryAcquire是需要子类具体去实现,其作用就是设置state的值,如果设 ...

  8. 有服务器端源码和客户端源码,C# 远程控制软件源码(含服务器端和客户端源码)...

    [实例简介]调试时 需要将ip地址 改成自己本机的ip地址 [实例截图] 需改 Server.cs和Client.cs中的ip地址即可,如下: [核心代码] using Microsoft.Win32 ...

  9. Java出租车后台管理控制系统web司机出勤车辆信息jsp源码mysql

    本项目为前几天收费帮学妹做的一个项目,Java EE JSP项目,在工作环境中基本使用不到,但是很多学校把这个当做编程入门的项目来做,故分享出本项目供初学者参考. 一.项目描述 这是一个基于Javaw ...

最新文章

  1. TensorFlow实现一元线性模型
  2. 集群系统实现方案详解
  3. UA MATH636 信息论2 数据压缩
  4. python如何去掉方括号_python从入门到实战外星人入侵
  5. 电大2007计算机机考专科试题,中央电大2007-2008学年度第一学期期末考试计算机网络专业计算机网络试题2008年1月...
  6. 一步一步学Silverlight 2系列(23):Silverlight与HTML混合之无窗口模式
  7. jquery模糊查询
  8. 3d制作中需要注意的问题_珠宝首饰工艺篇-戒指3D造型设计制作注意要点
  9. linux文件系统只有几k,关于Linux文件系统的的简单理解和认识
  10. 运维工程师如果将web服务http专变为https
  11. 硬链接与符号链接的比较?
  12. 详解各种光学仪器成像原理
  13. 【小程序入门】注册AppID为开发做准备
  14. 聊聊技术人的“绩效考核”
  15. 线性变换(1)——不变子空间
  16. Juniper路由器基本命令及中文解
  17. 外包公司究竟有没有前途?讲讲我在外包公司的真实经历
  18. 牛客 NC208246 胖胖的牛牛
  19. 给textView设置文字渐变色
  20. 达内python怎么样_在达内学Python怎么样?我能学会吗?

热门文章

  1. 【web安全】从2022中科大hackgame web中学习pdflatex RCE和python反序列化
  2. action='store_true'
  3. java发送s mime邮件_SpringBoot集成实现各种邮件发送
  4. SRRC认证的周期、费用多少?要什么资料?
  5. Base Filtering Engine (BFE)服务无法启动
  6. 说一说will-change
  7. 商业数据挖掘的13种应用场景,你了解多少?
  8. 景安服务器做网站seo怎样,虚拟主机和SEO优化的关系很大吗?景安
  9. 牛客小白月赛21 G.Game
  10. Python就业可选方向有哪些?带你了解Python主流职业选择!