java p2p 下载_java p2p文件传输(含服务器端与jsp源码)
【实例简介】
【实例截图】
【核心代码】
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源码)相关推荐
- java贪吃蛇游戏代码下载_java实现贪吃蛇游戏代码(附完整源码)
免费资源网,https://freexyz.cn/ 先给大家分享源码,喜欢的朋友点此处下载. 游戏界面 GUI界面 java实现贪吃蛇游戏需要创建一个桌面窗口出来,此时就需要使用java中的swing ...
- java treeset原理_Java集合 --- TreeSet底层实现和原理(源码解析)
概述 文章的内容基于JDK1.7进行分析,之所以选用这个版本,是因为1.8的有些类做了改动,增加了阅读的难度,虽然是1.7,但是对于1.8做了重大改动的内容,文章也会进行说明. TreeSet实现了S ...
- java pv实现_java实现UV.PV.IP统计的实现源码包
[实例简介] 统计网址的pv,uv,java如何实现数据统计,网站统计源码工程包 [实例截图] [核心代码] statistic └── statistic ├── src │ ├── appli ...
- java文件分割合并_java实现文件分割与合并 类示例源码
[实例简介] [实例截图] [核心代码] package cn.part.com; import java.io.BufferedInputStream; import java.io.Buffere ...
- java股票数据_java抓取东方财富股票数据(附源码)
背景 前段时间给朋友写了一个自动抓取同花顺股票数据的程序,不少人觉得不错. 这几天后台有粉丝给我留言让我也抓一下东方财富的数据,说东方财富的数据特别难抓,我还真不一定能搞得定. 本来我是一个德艺双磬且 ...
- java图书馆管理项目_java项目实战之图书馆管理系统(带源码和解析)
开发背景 图书馆是吉林省一家私营的中型图书馆企业.图书馆本着以读者为上帝为读者节省每一分钱的服务宗旨,企业利润逐年提高,规模不断壮大,经营图书品种.数量也逐渐增多.在企业不断发展的同时,企业传统的人工 ...
- java中acquire()_Java高并发系列之AQS中acquire源码解析
我们知道,AQS中最重要的两个方法就是acquire和release方法.我们本文来走读走读acquire的源码. 首先,tryAcquire是需要子类具体去实现,其作用就是设置state的值,如果设 ...
- 有服务器端源码和客户端源码,C# 远程控制软件源码(含服务器端和客户端源码)...
[实例简介]调试时 需要将ip地址 改成自己本机的ip地址 [实例截图] 需改 Server.cs和Client.cs中的ip地址即可,如下: [核心代码] using Microsoft.Win32 ...
- Java出租车后台管理控制系统web司机出勤车辆信息jsp源码mysql
本项目为前几天收费帮学妹做的一个项目,Java EE JSP项目,在工作环境中基本使用不到,但是很多学校把这个当做编程入门的项目来做,故分享出本项目供初学者参考. 一.项目描述 这是一个基于Javaw ...
最新文章
- TensorFlow实现一元线性模型
- 集群系统实现方案详解
- UA MATH636 信息论2 数据压缩
- python如何去掉方括号_python从入门到实战外星人入侵
- 电大2007计算机机考专科试题,中央电大2007-2008学年度第一学期期末考试计算机网络专业计算机网络试题2008年1月...
- 一步一步学Silverlight 2系列(23):Silverlight与HTML混合之无窗口模式
- jquery模糊查询
- 3d制作中需要注意的问题_珠宝首饰工艺篇-戒指3D造型设计制作注意要点
- linux文件系统只有几k,关于Linux文件系统的的简单理解和认识
- 运维工程师如果将web服务http专变为https
- 硬链接与符号链接的比较?
- 详解各种光学仪器成像原理
- 【小程序入门】注册AppID为开发做准备
- 聊聊技术人的“绩效考核”
- 线性变换(1)——不变子空间
- Juniper路由器基本命令及中文解
- 外包公司究竟有没有前途?讲讲我在外包公司的真实经历
- 牛客 NC208246 胖胖的牛牛
- 给textView设置文字渐变色
- 达内python怎么样_在达内学Python怎么样?我能学会吗?
热门文章
- 【web安全】从2022中科大hackgame web中学习pdflatex RCE和python反序列化
- action='store_true'
- java发送s mime邮件_SpringBoot集成实现各种邮件发送
- SRRC认证的周期、费用多少?要什么资料?
- Base Filtering Engine (BFE)服务无法启动
- 说一说will-change
- 商业数据挖掘的13种应用场景,你了解多少?
- 景安服务器做网站seo怎样,虚拟主机和SEO优化的关系很大吗?景安
- 牛客小白月赛21 G.Game
- Python就业可选方向有哪些?带你了解Python主流职业选择!