网络编程课程设计报告模版--java

广西大学计算机与电子信息学院

课程报告

( 20##——20##年度第一学期)

名    称:    网络编程课程设计报告

  院    系:         

班    级:          

学    号:           

学生姓名:                

指导教师:           

成    绩:                         

          

    日期:  2016    年   1  月   12   日


  

1. 设计任务................................................ 1

2. 设计步骤................................................ 1

2.1  程序设计原理................................................................ 1

2.2  关键代码解释................................................................ 1

3. 遇到的问题及相应解决办法................................. 1

4. 个人体会及建议.......................................... 1

参考文献................................................... 1


1. 设计任务

本次课程设计是一个简单的聊天室,就像上次课程报告一样,不过这次课程设计的聊天室更加的完善,并且用的是java来编程的,这次设计的功能要求有:
      (1)在服务器端和客户端分别创建一个套接字对象,通过输入输出流连接在一起。套接字调用close()方法关闭双方的套接字连接。

 (2)使用多线程处理套接字连接,把服务器端或客户端读取的数据放在一个单独的线程中去进行,防止服务器端或客户端读取数据可能引起的堵塞。服务器端收到一个客户的套接字后,应该启动一个专门为该客户服务的线程。

 (3)成功连接后,在图形界面中用户可以根据自己的需要进行不同的操作,如:群聊天、和某一个用户单独聊天(可加入生动的表情描述)、发送文件等。在界面中会显示用户的聊天记录。

2. 设计步骤

2.1  程序设计原理

 1、套接字Socket的建立、连接、关闭,客户端和服务器端的输入/输出流的连接。Java中的多线程及线程的常用方法、Runnable接口。基于SWING的图形用户界面设计:布局设计、文本组件、按钮与标签组件、列表组件等。InetAddress类。输入/输出流:文件、文件字节流、文件字符流、缓冲流、数据流。

2、Socket socket = new Socket(String host,int port);客户端创建Socket对象,host是服务器端的IP地址,port是一个端口号,该对象用于连接服务器。

3、BufferedReader br=new BufferedReader

(new InputStreamReader(socket.getInputStream())); 创建一个使用默认大小输入缓冲区的缓冲字符输入流。该输入流的指向是一个Reader流,Reader流将数据读入缓冲区,BufferedReader再从缓冲区中读取数据。InputStreamReader是字节流通向字符流的桥梁:它使用指定的charset读取字节并将其解码为字符。getInputStream()获取字节输入流。

4、PrintStream ps = new PrintStream(socket.getOutputStream());创建新的打印流,PrintStream 为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。它还提供其他两项功能。与其他输出流不同,PrintStream 永远不会抛出 IOException;而是,异常情况仅设置可通过 checkError 方法测试的内部标志。

5、File file = getFile();调用getFile()函数返回一个file的的路径,提示用户输入一个路径,判断是否存在该文件, 如果输入非法给予提示, 重新输入。

6、ps.println(file.getName()); ps.println(file.length());将文件名和大小发送到服务端。

7、String msg = br.readLine();if("已存在".equals(msg)){} 接收服务器发送回来的是否存在的结果. 如果文件已存在, 打印提示, 客户端退出. 如果不存在, 准备开始上传。

8、long finishLen = Long.parseLong(msg);  服务器端文件的长度。

9、FileInputStream fis = new  FileInputStream(file); 创建FileInputStream从文件中读取数据,OutputStream out = socket.getOutputStream();输出字节流,输出流接收输出字节并将这些字节写出到Socket的输出流。

10、fis.skip(finishLen);  从输入流中跳过并丢弃finishLen个字节的数据,即跳过服务端已完成的大小。

11、len = fis.read(byte[] buffer)); 从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。

12、out.write(byte[] b,int off,int len) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。

2.2  关键代码解释

(对设计任务中的核心代码按照功能进行分类介绍。)

服务器端:

package chat;

import java.net.*;

import java.io.*;

import java.util.*;

public class ChatServer{

    public static void main(String[] args)throws Exception{

        ServerSocket svSocket =null;

        Vector threads = new Vector();     

        try {

            svSocket = new ServerSocket(5555);

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

        }catch (Exception ex) {

            System.out.println ("Server create ServerSocket failed!");

            return;

        }

        try{

            int nid = 0;

            while(true){

                Socket socket = svSocket.accept();

                System.out.println ("accept a client");

                ServerThread st = new ServerThread(socket,threads);

                st.setID(nid++);

                threads.add(st);

                new Thread(st).start();

                for(int i=0;i < threads.size();i++){

                    ServerThread temp = (ServerThread)threads.elementAt(i);

                }

                System.out.println ("Listen again...");

            }

        }catch(Exception ex){

            System.out.println ("server is down");

        }

    }

}

class ServerThread implements Runnable{

    private Vector threads;

    private Socket socket = null;

    private DataInputStream in = null;

    private DataOutputStream out = null;

    private int nid;

    public ServerThread(Socket socket,Vector threads){

        this.socket = socket;

        this.threads = threads;

        try {

            in = new DataInputStream(socket.getInputStream());

            out = new DataOutputStream(socket.getOutputStream());

        }

        catch (Exception ex) {

        }

    }

    public void run(){

        System.out.println ("Thread is running");

        try{

            while(true){

                String receive = in.readUTF();

                if(receive == null)   return;

                //下线通知

                if(receive.contains("黯然下线了")){

                    for(int i=0;i < threads.size();i++){

                        ServerThread st = (ServerThread)threads.elementAt(i);

                        st.write("***"+receive+"***");

                    }

                }

                //上线通知

                else if(receive.contains("上线了")){

                    for(int i=0;i < threads.size();i++){

                        ServerThread st = (ServerThread)threads.elementAt(i);

                        st.write("<"+getID()+">: "+receive);

                    }  

                }

                //作为服务器监听中

                else if(receive.contains("监听中")){

                    for(int i=0;i < threads.size();i++){

                        ServerThread st = (ServerThread)threads.elementAt(i);      

                        st.write("***"+receive+"*** ");

                    }

                }

                //发送消息

                else if(receive.contains("说")){

                    //发送广播消息

                    if(receive.contains("大家")){

                        for(int i=0;i < threads.size();i++){

                            ServerThread st = (ServerThread)threads.elementAt(i);

                            st.write("<"+getID()+">: "+receive);

                        }

                    }

                    //发送指定消息

                    else{

                        int temp=receive.indexOf("<");

                        int temp1=receive.indexOf(">");

                        //获得接收者ID号

                        String tempS=receive.substring(temp+1,temp1);

                        int i=Integer.parseInt(tempS);

                        //指定接收者输出

                        ServerThread st = (ServerThread)threads.elementAt(i);

                        st.write("<"+getID()+">: "+receive);

                        //发送者自己也输出

                        st = (ServerThread)threads.elementAt(getID());

                        st.write("<"+getID()+">: "+receive);

                    }

                }

                else{

                    ServerThread st = (ServerThread)threads.elementAt(getID());

                    st.write("***"+receive+"***");

                }

            }

        }catch(Exception ex){

            threads.removeElement(this);

            ex.printStackTrace();

        }

        try{

            socket.close();

        }catch(Exception ex){

            ex.printStackTrace();

        }

    }

    public void write(String msg){

        synchronized(out){

            try{

                out.writeUTF(msg);

            }catch(Exception ex){

            }

        }

    }

    public int getID(){

        return this.nid;

    }

    public void setID(int nid){

        this.nid = nid;

    }

}

服务器端的文件传送:

package chat;

import java.io.BufferedReader;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.PrintStream;

import java.net.ServerSocket;

import java.net.Socket;

import java.text.SimpleDateFormat;

import java.util.Date;

import javax.swing.JOptionPane;

public class filesendServer{

    public void filereceive() throws Exception{

         //1.创建ServerSocket, 在循环中接收客户端请求, 每接收到一个请求就开启新线程处理

          ServerSocket serverSocket = new ServerSocket(1234);

          JOptionPane.showMessageDialog(null,"服务已启动,绑定1234端口!");

          while(true){

              Socket socket =  serverSocket.accept();

              new fileServerThread(socket).start();

          }

    }

}

class fileServerThread extends Thread{

    Socket socket;

    public fileServerThread(Socket socket) {

        this.socket = socket;

    }

    public void run() {

        FileOutputStream fos = null;

        try {

            //3.获取输入输出流

BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

PrintStream ps = new PrintStream(socket.getOutputStream());

            //7.接收文件, 查找是否存在. 如果存在, 给写一个消息给客户端, 服务端线程结束. 如果不存在, 写消息给客户端, 准备开始上传.

            String fileName = br.readLine();

            long fileLen  = Long.parseLong(br.readLine());

            File dir = new File("upload");

            dir.mkdir();

            File file = new File(dir,fileName);

            if(file.exists() && file.length() == fileLen){  // 文件已存在, length()即为文件大小, 文件不存在length()为0

                ps.println("已存在");

                return;

            }

            else{

                ps.println(file.length()); // 文件已存在, length()即为文件大小, 文件不存在length()为0

            }

            //10.从Socket的输入流中读取数据, 创建FileOutputStream写出到文件中

            String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());

            System.out.println(time + " "+ (file.exists() ? " 开始断点续传: " : " 开始上传文件: ") + file.getName());

            long start = System.currentTimeMillis();

            InputStream in = socket.getInputStream();

            fos = new FileOutputStream(file, true);  // 文件存在就追加, 文件不存在则创建

            byte[] buffer = new byte[1024];

            int len;

            while((len = in.read(buffer)) != -1){  //这个地方会堵塞,如果客服端没有关闭socket.服务器端读不到流末尾(-1)

            fos.write(buffer, 0, len);

            if(file.length() == fileLen) // 文件大小等于客户端文件大小时, 代表上传完毕

                    break;

            }

            fos.close();

            long end = System.currentTimeMillis();

            time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());

            System.out.println(time + " " + " 上传文件结束: " + file.getName() + ", 耗时: " + (end - start) + "毫秒");

            ps.println("上传成功");

            socket.close();

        } catch (IOException e) {

            if(fos != null)

                try {

                    fos.close();

                } catch (IOException e1) {

                    e1.printStackTrace();

                }

        }

    }

}

客户端的界面设计:

package chat;

import java.awt.*;

import java.io.*;

import java.net.*;

import java.awt.event.*;

import javax.swing.*;

public class Client

{

 public static void main(String args[])

 {

  new ChatClient();

  }

}

class ChatClient extends Frame implements ActionListener, Runnable{

    private static final long serialVersionUID = -4149839042245330513L;

    public Button listen,connection,sendtoall,sendtoone,exit,filesend;

    public JComboBox emote;

    public TextField inputName,inputContent;

    public TextArea chatResult;

    public Socket socket=null;

    public DataInputStream in=null;

    public DataOutputStream out=null;

    public Thread thread;

    ChatClient()

    {

        socket=new Socket();

        Box box1=Box.createHorizontalBox();

        listen=new Button("作为服务器监听");

        connection=new Button("连接服务器");

        filesend=new Button("发送文件");

        exit=new Button("退出");

        sendtoall=new Button("群聊");

        sendtoone=new Button("私聊");

        listen.setEnabled(false);

        filesend.setEnabled(false);

        sendtoall.setEnabled(false);

        sendtoone.setEnabled(false);

        inputName=new TextField(6);

        inputName.setBackground(new Color(162,231,250));

        inputContent=new TextField(22);

        inputContent.setBackground(new Color(162,231,250));

        chatResult= new TextArea("", 17,20,TextArea.SCROLLBARS_VERTICAL_ONLY);

        chatResult.setBackground(new Color(162,231,250));

        JLabel jlname=new JLabel("输入昵称");

        box1.add(jlname);

        box1.add(inputName);

        box1.add(listen);

        box1.add(connection);

        box1.add(filesend);

        box1.add(exit);

        Box box2=Box.createHorizontalBox();

        emote = new JComboBox();

        emote.setModel(new DefaultComboBoxModel(new String[] { "表情", "微笑",

            "甜笑", "惊喜", "嘻嘻", "扮酷", "嘿嘿", "傻笑", "好奇", "媚眼", "鬼脸", "陶醉",

            "害羞", "生气", "嚷嚷", "发怒", "伤心", "高明", "菜鸟", "问号", "狂笑", "大哭",

            "示爱", "呻吟", "想想" }));

        emote.setEnabled(false);

        JLabel jlintput = new JLabel("输入聊天内容");

        box2.add(jlintput);

        box2.add(inputContent);

        box2.add(emote);

        box2.add(sendtoall);

        box2.add(sendtoone);

        listen.addActionListener(this);

        connection.addActionListener(this);

        filesend.addActionListener(this);

        exit.addActionListener(this);

        sendtoall.addActionListener(this);

        sendtoone.addActionListener(this);

        Box box3=Box.createHorizontalBox();

        box3.add(chatResult);

        thread=new Thread(this);

        Box box0=Box.createVerticalBox();

        box0.add(Box.createVerticalStrut(10));

        box0.add(box1);

        box0.add(Box.createVerticalStrut(10));

        box0.add(box3);

        box0.add(Box.createVerticalStrut(10));

        box0.add(box2);

        box0.add(Box.createVerticalStrut(10));

        add(box0);

        setBounds(10,30,500,400);

        setBackground(new Color(80,212,248));

        setVisible(true);

        validate();

        addWindowListener(new WindowAdapter(){

            public void windowClosing(WindowEvent e){

                System.exit(0);

                try {

                    socket.close();

                } catch (IOException e1) {

                    e1.printStackTrace();

                }

            }

       });

    }  

    public void actionPerformed(ActionEvent e) {

        ActionProcess actionProcess=new ActionProcess(this);

        try {

            actionProcess.action(e);

        } catch (Exception e1) {

            e1.printStackTrace();

        }

    }

    public void run()

    {

        String s=null;

        while(true)

        {

            try

            {

                s=in.readUTF();

                chatResult.append("\n"+s);

            }

            catch(IOException e)

            {

                chatResult.setText("与服务器断开连接");

                try

                {

                    socket.close();

                }

                catch(Exception ep){}

                break;

            }

        }

    }

}

客户端的界面事件处理

package chat;

import java.awt.event.ActionEvent;

import java.io.DataInputStream;

import java.io.DataOutputStream;

import java.io.IOException;

import java.net.*;

import javax.swing.JOptionPane;

public class ActionProcess implements Runnable {

    private ChatClient client;

    String name="";

    String sendtoname="";

    String sendtoID;

    String filename="";

    String filepath="";

    public ActionProcess(ChatClient client) {

        this.client=client;

    }

    public void action(ActionEvent e)throws Exception{

        if(e.getSource()==client.connection)

        {

            try

            {

                if(client.socket.isConnected()){}

                else

                {

                    String addr=JOptionPane.showInputDialog("请输入服务器IP:");

                    InetAddress address=InetAddress.getByName(addr);

                    InetSocketAddress socketAddress=new InetSocketAddress(address,5555);

                    client.socket.connect(socketAddress);

                    client.in=new DataInputStream(client.socket.getInputStream());

                    client.out=new DataOutputStream(client.socket.getOutputStream());

                    name=client.inputName.getText();

                    client.out.writeUTF("姓名为"+name+"的朋友风尘仆仆地上线了...");

                    client.listen.setEnabled(true);

                    client.filesend.setEnabled(true);

                    client.sendtoall.setEnabled(true);

                    client.sendtoone.setEnabled(true);

                    client.emote.setEnabled(true);

                    if(!(client.thread.isAlive()))

                        client.thread=new Thread(this);

                    client.thread.start();

                }

            }

            catch(IOException ee){}

        }

        if(e.getSource()==client.listen)

        {

            try

            {

                name=client.inputName.getText();

                client.out.writeUTF("姓名为"+name+"的朋友正在监听中...");  

                filesendServer filesendserver=new filesendServer();

                filesendserver.filereceive();

            }

             catch (Exception ee) {

                ee.printStackTrace();

            }

        }

        if(e.getSource()==client.filesend){

            if(client.socket.isConnected())

            try {

                filesendClient filesendclient=new filesendClient();

                filesendclient.filesend();

                client.out.writeUTF("成功发送文件!");

            }catch (Exception ee){}    

        }

        if(e.getSource()==client.exit)

        {  if(client.socket.isConnected())

            try {

                name=client.inputName.getText();

                client.out.writeUTF("姓名为"+name+"的朋友黯然下线了...");

                client.out.flush();

                client.out.close();

                client.socket.close();

            } catch (IOException e1) {

                e1.printStackTrace();

            }

            System.exit(0);

        }

        String em=client.emote.getSelectedItem().toString();

        if (em.equals("表情")) {

            em = "";

        } else {

            em += "着";

        }

        if(e.getSource()==client.sendtoall)

        {

            if(client.socket.isConnected()){

                name=client.inputName.getText();

                String s=client.inputContent.getText();

                if(s!=null)

                {

                    try

                    {

                        client.out.writeUTF(name+em+"对大家说:"+s);

                        client.out.flush();

                        client.inputContent.setText("");

                    }

                    catch(IOException e1){}

                }

            }

        }

        if(e.getSource()==client.sendtoone)

        {  

            if(client.socket.isConnected()){

                sendtoID=JOptionPane.showInputDialog("请输入对方ID:");

                sendtoname=JOptionPane.showInputDialog("请输入对方姓名:");

                String s=client.inputContent.getText();

                name=client.inputName.getText();

                if(s!=null)

                {

                    try

                    {

                        client.out.writeUTF(name+"悄悄地"+em+"对<"+sendtoID+">"+sendtoname+"说:"+s);

                        client.out.flush();

                        client.inputContent.setText("");

                    }

                    catch(IOException e1){}

                }

            }

       }

    }

    public void run()

    {

        String s=null;

        while(true)

        {

            try

            {

                s=client.in.readUTF();

                client.chatResult.append("\n"+s);

            }

            catch(IOException e)

            {

                client.chatResult.setText("与服务器断开连接");

                try

                {

                    client.socket.close();

                }

                catch(Exception ep){}

                break;

            }

        }

    }

}

客户端的文件接收

package chat;

import java.io.BufferedReader;

import java.io.File;

import java.io.FileInputStream;

import java.io.InputStreamReader;

import java.io.OutputStream;

import java.io.PrintStream;

import java.net.Socket;

import javax.swing.JOptionPane;

public class filesendClient {

    public void filesend() throws Exception{

        //1.创建Socket, 指定服务端IP地址和端口号, 连接服务器

        String sendtoIP=JOptionPane.showInputDialog("请输入对方IP:");

        Socket socket = new Socket(sendtoIP, 1234);

        //2.获取输入输出流

        BufferedReader br = new BufferedReader(

new InputStreamReader(socket.getInputStream()));

        PrintStream ps = new PrintStream(socket.getOutputStream());

        //3.提示用户输入一个路径,判断是否存在是否是文件, 如果输入非法给予提示, 重新输入

        File file = getFile();

        //4.将文件名和大小发送到服务端

        ps.println(file.getName());

        ps.println(file.length());

        //5.接收服务器发送回来的是否存在的结果. 如果文件已存在, 打印提示, 客户端退出. 如果不存在, 准备开始上传.

        String msg = br.readLine();

        if("已存在".equals(msg)){

            JOptionPane.showMessageDialog(null,"文件已存在,请不要重复上传!");

            return;

        }

        long finishLen = Long.parseLong(msg); // 服务器端文件的长度

        //6.创建FileInputStream从文件中读取数据, 写出到Socket的输出流

        FileInputStream fis = new  FileInputStream(file);

        OutputStream out = socket.getOutputStream();

        byte[] buffer = new byte[1024];

        int len;

        fis.skip(finishLen); // 跳过服务端已完成的大小

        while((len = fis.read(buffer)) != -1)

            out.write(buffer, 0, len);

        fis.close();

        socket.close();

    }

    public File getFile() throws Exception{  //得到文件的方法

        File file=null;

        boolean flag=false;

        while(flag==false){ 

            String filepath=JOptionPane.showInputDialog("请输入要上传的路径:");

            file = new File(filepath);

            if(!file.exists()){

            JOptionPane.showMessageDialog(null,"您输入的路径不存在,请重新输入!");

                flag=false;

            }

            else if(file.isDirectory()){

               JOptionPane.showMessageDialog(null,"占不支持文件夹上传!请输入一个文件路径!");

                flag=false;

            }

            else flag=true;

        }

        return file;

    }

}

实验截图:

3. 遇到的问题及相应解决办法

本次编程的主要问题是界面的编程。因为有了上次的实验做基础,在设计Socket等方面没什么问题。但是界面的设计因为没动过手,因此比较陌生,在设计过程出了很多问题,也查了很多书,最后也成功地解决问题。

4. 个人体会及建议

通过这次课程设计,使我对网络编程和java有了更进一步的认识和了解,也让我学会了界面制作的一些知识。要想学好网络编程要重在实践,必须通过不断的实践操作才能更好地掌握它。我也发现我的好多不足之处,首先是自己在基础上还不行,经常出错,通过学习已有所改进;再有对java的一些标准库函数不太了解,还有对函数调用的正确使用不够熟悉,还有对java中经常出现的错误也不了解,通过实践的学习,我认识到学好计算机要重视实践操作,不仅仅是学习java,还是其它的语言和学科,以及其它的计算机方面的知识都要重在实践,所以后在学习过程中,我会更加注视实践操作,使自己更好地学好计算机。如果要我自评分,我给自己打70分。

通过上网查询收集资料和同学的交流,让我觉得要完成一个任务,一个人悄无声息是很难做好的,和同学交流研究会使我们获得更多,也能使自己少走许多弯路,事半功倍。这给我启示,学习一定要勇于实践,虚心请教。

 在课程设计过程中,收获知识,提高能力的同时,我也学到了很多人生的哲理,懂得怎么样去制定计划,怎么样去实现这个计划,并掌握了在执行过程中怎么样去克服心理上的不良情绪。因此在以后的生活和学习的过程中,我一定会把课程设计的精神带到生活中,不畏艰难,勇往直前!

参考文献

 [1] 电子工业出版社《JAVA程序设计实用教程》,叶核亚编著考资料  

 [2] 清华大学出版社《Java程序设计与实践教程》,王微,董迎红著

相关推荐