admin 管理员组

文章数量: 1184232


2024年1月10日发(作者:单片机编程注意事项)

文件传输协议的简单设计与实现

摘要:

文件传送是各种计算机网络都实现的基本功能,文件传送协议是一种最基本的应用层协议按照客户/服务器的模式进行工作,提供交互式的访问,是INTERNET使用最广泛的协议之一。本设计是用JAVA语言简单实现文件传输协议,利用SOCKET以及SERVERSOCKE等类方法,当中实现了上传、下载、获取服务器目录等基本文件传输功能。

关键字:文件传输、FTP。

1 具体设计任务

1.1实验内容

我们的计算机网络实验环境建立在TCP/IP 网络体系结构之上。各计算机除了安装TCP/IP 软件外,还安装了TCP/IP 开发系统。实验室各计算机具备Windows环境中套接字socket 的编程接口功能,可为用户提供全网范围的进程通信功能。本实验要求学生利用这些功能,设计和实现一个简单的文件传送协议。

1.2具体要求

用socket 编程接口编写两个程序,分别为客户程序(client.c)和服务器程序(server.c),该程序应能实现下述命令功能:

get:取远方的一个文件

put:传给远方一个文件

pwd:显示远主当前目录

dir:列出远方当前目录

cd :改变远方当前目录 :显示你提供的命令

quit :退出返回

此命令的具体工作方式(指给出结果的形式)可以参照FTP 的相应命令,有余力的同学可以多实现几个命令。

2 基本思路及所涉及的相关理论

2.1 文件传输协议

网络协议是网络中计算机与终端之间正确传送信息和数据的规范格式,起包括语法、语义和时序这三部分。文件传输协议(File Transfer Protocol, FTP)是在TCP/IP网

络中传输文件的一种格式规范,其规定在用户和服务器之间开设两个通信端口:控制端口和数据端口。前者生存周期为从用户登录开始直至用户登出,后者则在进行数据传送的时候打开,并且在数据传送完毕之后立即结束。控制端口用来监听双方共同规定的控制字以达到及时提供服务或响应,数据端口则要先将文件拆分成分组再进行传送,这样做的目的是为了更加好的适应网络中的带宽限制,以及减少传送期间节点的延时,以达到高速传送。

2.2 基本思路:

2.2.1 模拟FTP的工作模式,在双方工作的时候开设两个端口,作为控制端口(2332)和数据端口(2326)。

2.2.2 规范控制字如下:

LIST:

LOGIN:

GET:

PUT:

QUIT:

获得服务器目录

登陆

下载

上传

登出

对应服务器响应返回控制字:

555:

444:

000:

666:

888:

发送列表完毕

登录成功

登陆失败

下载结束

服务器关闭

2.2.3 模拟FTP工作机制,确定数据端口传送数据时,进行分组传送。

2.2.4 服务器从打开开始,保持监听控制端口,当用户登陆成功后,主动分配该用户服务线程。

2.2.5 在传送数据的时候,为了确保不影响原程序的工作,应独立分配线程。

3 方案设计(主要网络设备、网络拓扑结构设计图)

本设计基本设计图如下:

控制字传输

客户端 服务器

数据传输

4 网络具体配置步骤

4.1 服务器:

4.1.1 服务器界面:

JPanel jp1 = new JPanel(), jp2 = new JPanel(), jp3 = new JPanel();

JSplitPane jsp = new JSplitPane();

JSplitPane jsp1 = new JSplitPane(AL_SPLIT);

static JScrollPane jsc = new JScrollPane();

JPanel jp = new JPanel();

static String newpath = null;

static DefaultMutableTreeNode root;

static JTree tree;

String name;

String ipaddress;//实例化一些界面控件

ftpserver() {

super("服务器");//新建一个继承frame类的窗口

e(600, 500);//设置窗口大小

aultCloseOperation(_ON_CLOSE);

tentPane().add(jsp);//添加JSplitPane面板

iderLocation((int) (th() * 0.28));

tComponent(jsc);//设置JSplitPane面板左边的内容

htComponent(jsp1); //设置JSplitPane面板右边的内容

iderLocation((int) (ght() * 0.4));

JButton jb = new JButton("开始"), jb2 = new JButton("end"),

jb3 = new JButton("del"),jb4 = new JButton("浏览");

static JTextArea jt = new JTextArea();

boolean bool = true;

Component(jt);

htComponent(jp);

ionListener(this);

ionListener(this);

ionListener(this);

ionListener(this);//为按扭添加监听

(jb);

(jb2);

(jb3);

(jb4);//在面板中添加按扭

ticalScrollBarPolicy(AL_SCROLLBAR_ALWAYS);

izontalScrollBarPolicy(NTAL_SCROLLBAR_ALWAYS);

//设置滚动条方式

Toolkit kit = aultToolkit();

Dimension screenSize = eenSize();//获得屏幕窗口大小

Dimension frameSize = e();//获得当前程序窗口大小

if ( > ) {

}

if ( > ) {

}

ation(( - ) / 2,

( - ) / 2);//窗口居中算法

= ;

= ;

ible(true);//设置窗口可见

4.1.2 本地目录获得:

if((jb4)){//“浏览”按扭的响应事件

try{

JFileChooser jf=new JFileChooser();//打开一个文件选择窗口

eSelectionMode(ORIES_ONLY);//设置选择文件模式

int returnval = enDialog(this);

File chfile = ectedFile();//获得所选择的文件

newpath = olutePath();//获得所选文件的路径

if(returnval == E_OPTION){//“打开”按钮的响应事件

flush();//调用flush函数

}

else {

ssageDialog(this,"没有选择文件");

}

}catch(Exception ee){

}

}

//flush函数

protected void flush() {

DefaultMutableTreeNode dd = new DefaultMutableTreeNode(newpath);

tree = new JTree(dd);//新建一个结点为dd的树构造

setTree(dd, newpath);//调用setTree函数

wport().setView(tree);//将生成的树插入滚动条中

Row(0);//展开根结点

eSelectionListener(this);//为树结点添加选择响应监听

}

//setTree函数

private static void setTree(DefaultMutableTreeNode root2, String path) {

File file = new File(path);

String[] fname = ();//获path路径下的目录和文件名

for (int j = 0; j < ; j++) {

File f = new File(olutePath()+""+fname[j]);

if (()) {//是文件则添加文件

DefaultMutableTreeNode d = new DefaultMutableTreeNode(fname[j]);

(d);

} else {//是目录则添加目录

DefaultMutableTreeNode d = new DefaultMutableTreeNode(fname[j]);

(d);

setTree(d, olutePath());//递归生成目录下的内容

}

}

}

4.1.3 监听端口线程:

private void work() {

try {

socket = ();//监听端口

is = utStream();

br = new BufferedReader(new InputStreamReader(is));//建立输入流的数据缓冲

os = putStream();

ps = new PrintStream(os);

new Thread(new Runnable() {//启动线程

public void run() {

try {

while (socket != null) {

String frist = ne();//读取客户端发送的控制字

if (With("222")) {//客户端登陆请求

ipaddress = tAddress().getHostAddress();//获取客户端IP

String string = ing(4);

back = check(string);//调用check函数进行用户身份验证

if(back == 444){

n("444");//通知客户端验证成功

}else{

n("000");//通知客户端验证失败

}

}

if (With("list")) {//客户端获取服务器列表请求

List(1,newpath);

n("555 List complete!!");

}

if (With("get")) {//客户端下载请求

String name = ing(f("/")+1).trim();

get(name);

}

if (With("put")) {//客户端上传请求

String name = ing(4).trim();

put(name);

}

if (("Quit")) {//客户端退出通知

t((i--) + " 个用户在线!!");

bool = false;

('n' + "断开连接");

}

}

} catch (Exception e) {

}

}

}).start();

} catch (Exception e) {

tackTrace();

}

}

4.1.4 用户请求目录列表响应:

if (With("list")) {//客户端获取服务器列表请求

List(1,newpath);//调用List函数响应列表请求

n("555 List complete!!");//通知客户列表发送结束

}

//List函数

private void List(int b, String path) throws Exception {

File file = new File(path);

();

String[] fname = ();//获取path路径下的目录和文件名

try {

Socket data = new Socket(ipaddress, 2326);//建立Socket套接字

OutputStream os_data = putStream();//建立数据缓冲

PrintStream ps_data = new PrintStream(os_data);

prin(b, file, ps_data, fname);//调用prin函数

ps_();

ps_();

os_();

();//释放系统资源

} catch (IOException e) {

tackTrace();

}

}

//prin函数

private void prin(int b, File file, PrintStream ps_data, String[] fname) {

// TODO Auto-generated method stub

for (int t = 0; t < ; t++) {

File file2 = new File(olutePath() + "/" + fname[t]);

if (ctory()) {// 文件夹

String isDirectory = "-";

int c = b + 1;

ps_n(b + "|" + isDirectory + "|" + fname[t]);

prin(c, file2, ps_data, ());//递归发送文件夹下的内容

} else {// 文件

String isfile = "+";

ps_n(b + "|" + isfile + "|" + fname[t]);

}

}

}

4.1.5 下载响应:

if (With("get")) {//客户端下载请求

String name = ing(f("/")+1).trim();//获得客户请求下载的文件名

get(name);//调用get函数

}

//get函数

protected void get(final String name) {

new Thread(new Runnable(){//响应下载线程

public void run() {

// TODO Auto-generated method stub

File file = new File(newpath+""+name);//得到文件所在路径

int count;

if (()) {//文件

try {

Socket data = new Socket(ipaddress, 2326);//建立Socket套接字

OutputStream os_data = putStream();

RandomAccessFile sendfile = new RandomAccessFile(olutePath(),

"r");

byte[] bytebuffer = new byte[1024];//文件数据分组

while ((count = (bytebuffer)) != -1) {

os_(bytebuffer, 0, count);//传送数据

}

os_();

os_();

();

();

n("666 getfile complete!!");//传送完成,释放相应资源并通知客户

} catch (Exception e) {

tackTrace();

}

} else {

();

}

}

}).start();

}

4.1.6 上传响应:

if (With("put")) {//客户端上传请求

String name = ing(4).trim();//获得上传的文件的文件名

put(name);//调用put函数

}

//put函数

protected void put(final String name) {

new Thread(new Runnable(){//响应上传的线程

public void run() {

// TODO Auto-generated method stub

int count;

byte[] bytebuffer = new byte[1024];//建立数据缓冲

try {

Socket datasocket = ();//监听数据

InputStream is_data = utStream();

RandomAccessFile accfile =

RandomAccessFile(createfile().getAbsolutePath()+ "" + name, "rw");

while ((count = is_(bytebuffer)) != -1) {

(bytebuffer, 0, count);//接收数据并写入本地文件

}

();

is_();

new

();

n("777 sendfile complete!!");//文件接收完成,关闭相应资源并通知客户

} catch (FileNotFoundException e) {

tackTrace();

} catch (IOException e) {

tackTrace();

}

}

}).start();

}

4.1.7 登录响应:

if (With("222")) {//客户端登陆请求

ipaddress = tAddress().getHostAddress();//获取客户端IP

String string = ing(4);

back = check(string);//调用check函数进行用户身份验证

if(back == 444){

n("444");//通知客户端验证成功

}else{

n("000");//通知客户端验证失败

}

}

//check函数

protected int check(String string) {

try {

File f=new File(".");

FileReader fr = new

FileReader(olutePath().substring(0,olutePath().indexOf("."))+"");//读取当前目录下的用户文件

BufferedReader bb = new BufferedReader(fr);

String check = ne();

while (!(check)&& check != null) {//比较用户名和口令

check = ne();

}

if((check)){//验证成功

i++;

t("-------" + i + " 个用户在线!!");//显示用户数

return 444;// 返回444,开始准备数据传输;

}

return 001;//验证失败

} catch (Exception e) {

t("000 error");

return 001;

}

}

4.2 客户端:

4.2.1 客户端界面:

public class ftpframe extends JFrame implements ActionListener{

GridBagLayout gbl=new GridBagLayout();//采用网格布局方式

GridBagConstraints gbc=new GridBagConstraints();

MakeConstraints mc=new MakeConstraints();

EditPane1 ed1=new EditPane1();

EditPane2 ed2=new EditPane2();

JListPanec jlp1=new JListPanec();

ButtonPane bp=new ButtonPane();

JListPanes jlp2 = new JListPanes();

StatePane sp=new StatePane();

static DefaultMutableTreeNode root = new DefaultMutableTreeNode("服务器");

static JTree ftree = new JTree(root);//实例界面控件

static Socket socket;

static Socket ss;

static Socket s;

static ServerSocket so;

static InputStream is;

static InputStream is_data;

static OutputStream os;

static PrintStream ps;

static BufferedReader br;

static boolean bool = true;

static String sip=null;

String ftreename = null;

static JScrollPane jl = new JScrollPane();

ftpframe(){

super("FTP客户端");//新建一个继续Frame类的窗口

setDefaultCloseOperation(EXIT_ON_CLOSE);

setSize(800,500);

getContentPane().setLayout(gbl);

(gbc, 0, 0, 2, 1,

,EST);

straints(ed1, gbc);

getContentPane().add(ed1);

(gbc, 2, 0, 1, 1,

,EST);

straints(ed2, gbc);

getContentPane().add(ed2);

(gbc, 0, 1, 1, 1,

,EST);

straints(jlp1, gbc);

getContentPane().add(jlp1);

(gbc, 1, 1, 1, 1,

,EST);

straints(bp, gbc);

getContentPane().add(bp);

50, 10,

50, 10,

40, 80,

30, 80,

(gbc, 2, 1, 1, 1, 30, 80,

,EST);

straints(jlp2, gbc);

getContentPane().add(jlp2);

(gbc, 0, 2, 3, 1, 100, 10,

,EST);

straints(sp, gbc);//网格布局设置

getContentPane().add(sp);

ionListener(this);

ionListener(this);

ionListener(this);

ionListener(this);

ionListener(this);//为按扭添加事件监听

Toolkit kit=aultToolkit();

Dimension screenSize=eenSize();//获得屏幕大小

Dimension frameSize=e();//获得程序窗口大小

if(>){

=;

}

if(>){

=;

}

ation(()/2,()/2);//居中算法使窗口居中

setResizable(false);

show();}

4.2.2 本地目录获得:

if(rce()==){//“浏览”按扭的响应事件

JFileChooser jfch=new JFileChooser();//打开一个文件选择窗口

eSelectionMode(ORIES_ONLY);//设置选择文件方式

int returnval=enDialog(this);

if(returnval==E_OPTION){//响应“打开”事件

File root2=ectedFile();//获取所选择的目录或文件名

if(())root2=entFile();//选择的是文件则取得它所属的目录名

DefaultMutableTreeNode

DefaultMutableTreeNode(h());

setTree(h(),rootTree2);//调用setTree函数构造树

t(rootTree2);

();

}

else

ssageDialog(this,"没有选择文件");

}

//setTree函数

public void setTree(String Path,DefaultMutableTreeNode TreePath){

try{

File source =new File(Path);

String[] filename=();//获取path路径下的目录和文件名

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

File filemen=new File(h(),filename[i]);

if(ctory()){//是目录则添加目录

DefaultMutableTreeNode

DefaultMutableTreeNode(e());

(TreeMen);

setTree(h(),TreeMen);//递归算法构造目录下的内容

}

else{//是文件则添加文件

DefaultMutableTreeNode

DefaultMutableTreeNode(e());

(TreeMen);

}

TreeMen=new

TreeMen=new

rootTree2=new

}

}

catch(Exception e){

ssageDialog(this, "出错了:"+e);

}

}

4.2.3 登录:

if(rce()==3){//"登陆"按钮

new login();//实例化一个login对象

}

//login()类

public class login extends JFrame implements ActionListener {

GridBagLayout gbl = new GridBagLayout();

GridBagConstraints gbc = new GridBagConstraints();

EditPane0 ed0 = new EditPane0();

EditPane1 ed1 = new EditPane1();

EditPane2 ed2 = new EditPane2();

ButtonPane bp = new ButtonPane();

MakeConstraints mc = new MakeConstraints();

static String user;

static String password;

static Thread th;

boolean bbb = true;

login() {

super("登陆");

setDefaultCloseOperation(EXIT_ON_CLOSE);

setSize(300, 300);

getContentPane().setLayout(gbl);

(gbc, 0, 0, 1, 1, 100, 25, ,

);

straints(ed0, gbc);

getContentPane().add(ed0);

(gbc, 0, 1, 1, 1, 100, 25, ,

);

straints(ed1, gbc);

getContentPane().add(ed1);

(gbc, 0, 2, 1, 1, 100, 25, ,

);

straints(ed2, gbc);

getContentPane().add(ed2);

(gbc, 0, 3, 1, 1, 100, 25, ,

);

straints(bp, gbc);

getContentPane().add(bp);

ionListener(this);

ionListener(this);

Toolkit kit = aultToolkit();

Dimension screenSize = eenSize();

Dimension frameSize = e();

if ( > ) {

= ;

}

if ( > ) {

= ;

}

ation(( - ) / 2,

( - ) / 2);

setResizable(false);

show();

}//界面布局设置

public void actionPerformed(ActionEvent e) {

if (rce() == 0) {//“确定”按扭的事件响应

bbb = true;

= t().trim();

user = t().trim();

password = t().trim();//获得用户填写的内容

if (("") || ("")) {

ssageDialog(null, new JLabel("请填写完整的登陆信息!"),

"出错了!", ATION_MESSAGE);

} else {

try {

= new ServerSocket(2326);

= new Socket(, 2332);//建立ServerSocket套接字

} catch (IOException e1) {

tackTrace();

}

try {

= putStream();

} catch (IOException e1) {

tackTrace();

}

= new PrintStream();

new Thread(new Runnable() {//启动客户线程

public void run() {

while (bbb) {

try {

= utStream();

BufferedReader br = new BufferedReader(new InputStreamReader());

String sr = ne();

if (With("444")) {//验证通过

bled(true);

Socket和

bled(true);

t("连接中");

bled(false);

ssageDialog(null, new JLabel("登陆成功!"));

new Thread(new Runnable() {

//省略部份代码

public void run() {„}}.start//启动List处理线程

}

if (With("555")) {//List传送完毕

= false;

}

if (With("888")) {//服务器退出

();

();//关闭套接字

bled(false);

bled(false);

t("断开");

ssageDialog(null,new JLabel("与FTP服务器退出连接!"));

}

if (("000")) {//验证失败

ssageDialog(null, "认证失败");

();

();//关闭套接字

bbb = false;

// if(th!=null)th=null;

}

} catch (IOException e) {

// ssageDialog(null, new

// JLabel("连接FTP服务器失败!"));

}

}

setVisible(false);

}

}).start();

n("222 Loginuser" + user + "pass" + password);//发送用户信息给服务器进行验证

setVisible(false);

}

}

if (rce() == 1) {//“取消”按扭事件响应

setVisible(false);

}

}

class MakeConstraints {//布局设置

void set(GridBagConstraints gbc0, int gridx, int gridy, int gridwidth,

int gridheight, double weightx, double weighty, int fill,

int anchor) {

= gridx;

= gridy;

dth = gridwidth;

ight = gridheight;

x = weightx;

y = weighty;

= fill;

= anchor;

}

}

class EditPane0 extends JPanel {//界面布局

JLabel jl0 = new JLabel("目标主机IP:");

JTextField jft = new JTextField(15);

FlowLayout fl = new FlowLayout();

EditPane0() {

setLayout(fl);

add(jl0);

add(jft);

}

}

class EditPane1 extends JPanel {//界局布局

JLabel jl0 = new JLabel("用户名:");

JTextField jft = new JTextField(15);

FlowLayout fl = new FlowLayout();

EditPane1() {

setLayout(fl);

add(jl0);

add(jft);

}

}

class EditPane2 extends JPanel {//界面布局

JLabel jl0 = new JLabel("口令:");

JPasswordField jft = new JPasswordField(15);

FlowLayout fl = new FlowLayout();

EditPane2() {

setLayout(fl);

add(jl0);

add(jft);

}

}

class ButtonPane extends JPanel {//界面布局

JButton jb0 = new JButton("确定");

JButton jb1 = new JButton("取消");

FlowLayout fl = new FlowLayout();

ButtonPane() {

setLayout(fl);

add(jb0);

add(jb1);

}

}

}

4.2.4 请求目录列表:

new Thread(new Runnable() {//启动List处理线程

public void run() {

try {

= true;

File cf=new File(".");

FileWriter fw = new

FileWriter(olutePath().substring(0,olutePath().indexOf("."))+"");//建立List数据文件

n("list");//发送目录列表请求

ftpframe.s = ();//监听数据

_data = utStream();

BufferedReader br0 = new BufferedReader(new

InputStreamReader(_data));

String str = ne();//读出数据

while (|| str != null) {

if (str != null) {

(str + 'n');//写入文件

str = ne();

}

}

();

_();

();//释放资源

DefaultMutableTreeNode dd = new DefaultMutableTreeNode("服务器");

= new JTree(dd);//新建目录树

ee(dd, 0);//调用setftree函数构建树

Row(0);//展开根结点

wport().setView();//将树插入滚动条

} catch (Exception e) {

}

}

}).start();

4.2.5 下载:

if(rce()==1){//"下载"按钮事件响应

new Thread(new Runnable(){//下载线程

public void run() {

// TODO Auto-generated method stub

if(ectionPath()!=null&&ectionPath()!=null){

String sdirs=new String(ectionPath().toString().substring(1,

ectionPath().toString().lastIndexOf("]")));//获得下载的文件名

n("get "+eAll(", ","/"));//发送下载请求和文件名

String dirs=new

String(ectionPath().toString().substring(1,

ectionPath().toString().lastIndexOf("]")));//获得本地保存路径

File re0=new File(eAll(", ","/"));

if(ctory()){

try {

s = ();//监听数据

is_data = utStream();

RandomAccessFile accfile = new RandomAccessFile(eAll(",

","/")+"/"+ectionPath().toString().substring((ectionPath()).toString().lastIndexOf(",")+1,(ectionPath()).toString().lastIndexOf("]")), "rw");//建立本地相应文件

byte[] bytebuffer = new byte[1024];//建立数据缓冲

int count = 0;

while ((count = is_(bytebuffer)) != -1) {

(bytebuffer, 0, count);//读取数据写入本地文件

}

DefaultMutableTreeNode

DefaultMutableTreeNode(eAll(", ","/"));

setTree(eAll(", ","/"),rootTree2);

t(rootTree2);

();//这4句刷新当前目录的树视图

ssageDialog(null,new JLabel("下载成功!"));

();

is_();

();//释放相应资源

} catch (Exception ew) {

tackTrace();

}

}

else

ssageDialog(null, "请选择一个文件夹用于下载");

}

else

ssageDialog(null, "请选择一个文件夹或文件用于下载");

}

}).start();

}

4.2.6 上传:

if(rce()==0){//"上传"按钮事件响应

try {

new Thread(new Runnable() {//上传线程

public void run() {

rootTree2=new

try {

if(ectionPath()!=null){

String dirs=new

String(ectionPath().toString().substring(1,

ectionPath().toString().lastIndexOf("]")));//得到本地文件路径

File re=new File(eAll(", ","/"));

if(()){

n("put"+ectionPath().toString().substring((ectionPath()).toString().lastIndexOf(",")+1,(ectionPath()).toString().lastIndexOf("]")));//发送上传请求和文件名

ss = new Socket(sip, 2326);//建立Socket套接字

os = putStream();

int count;

RandomAccessFile f = new RandomAccessFile(eAll(", ","/"), "r");

byte[] bytebuffer = new byte[1024];//数据缓冲

while ((count = (bytebuffer)) != -1) {

(bytebuffer, 0, count);//传送数据

}

ssageDialog(null,new JLabel("上传成功!"));

();

();

();//上传成功,关闭相应资源

bool = true;

File ccf=new File(".");

FileWriter fw = new

FileWriter(olutePath().substring(0,olutePath().indexOf("."))+"");

n("list");//请求获得新的列表

s = ();//监听数据

is_data = utStream();

BufferedReader br0 = new BufferedReader(new InputStreamReader(is_data));

String str = ne();//读取数据

while (bool||str != null) {

if (str != null) {

(str + 'n');

str = ne();}

}

();

is_();

();

DefaultMutableTreeNode dd = new DefaultMutableTreeNode("服务器");

ftree = new JTree(dd);

setftree(dd, 0);//根据新的列表重构目录树

Row(0);//展开根结点

wport().setView(ftree);

}

else

ssageDialog(null, "请选择一个文件!!");

}

else

ssageDialog(null, "请选择一个文件!!");

}catch (Exception e) {

}

}

}).start();

}catch (Exception eeee) {

tackTrace();

}

}

5 调试过程中出现的问题及相应解决办法

5.1 SOCKET以及SERVERSOCKET的应用问题

由于数据传输端口只在需要的时候打开并且在传送完毕后立即关闭,所以经常会在关闭之后端口不再打开;而且在登录失败时,要断开控制字端口来避免本地端口的占用。解决办法:在利用SOCKET以及SERVERSOCKET这两个类方法的时候,用BOOLEAN变量作为控制端口的开关。

5.2 客户端界面的目录文件树与本地及服务器目录文件一一对应问题

客户端界面中用JTree类构造本地的目录文件树和服务器的目录文件树。为了使界面的操作映射到本地或服务器系统中相应的文件操作,需要获得文件的路径。

解决方法:用JTree类的getSelectionPath()方法获得路径信息,但这些信息并不是正确的路径格式,因此还需要用String类下的substring进行处理。

5.3 资源的释放

程序中使用了Socket、ServerSocket套接字及多线程,在不需要使用套接字的时候应及时关闭,否则重复绑定的时候会抛出异常,无法使用。

解决方法:使用Socket、ServerSocket类的close()及时关闭套接字。

6 个人体会及建议

通过本次实验设计,熟悉了套接字Socket、ServerSocket 的编程接口功能和使用,了解文件传输的相应协议,多线程的使用和协作,初步掌握TCP/IP 网络应用程序基本的设计方法和实现技巧。

参考文献

[1] 叶至军.Java2自学教程[M].北京:人民邮电出版社,2004.10:第69页至第73页,第156页至第161页。

[2] 汪晓平,俞俊,李功.精通Java网络编程[M].北京:清华大学出版社,2005.9:第196页至第210页。


本文标签: 文件 端口 目录 数据 用户