网络编程

实验名称 实验七、网络编程 日期 2020年 07 月02 日
一、实验目的:
1、掌握URL类及其WWW连接。
2、掌握用ServerSocket和Socket类实现TCp/IP客户和服务器。
3、掌握用DatagramPacket和DatagramSocket进行基于UDP的网络通信。
4、了解用MulticastSocket实现多点广播。
二、实验环境:

PC+Windows10+Eclipse

三、实验内容:
(写出主要的内容)
1、使用URL读取桂林理工大学主页(http://www.glut.edu.cn),并在控制台打印输出。
代码:

package 实验七;
import java.net.*;
public class ParseURL {
	public static void main(String[] args) throws Exception{
		URL glut=new URL("http://www.glut.edu.cn");
		System.out.println("protocal="+glut.getProtocol());
		System.out.println("host="+glut.getHost());
		System.out.println("port="+glut.getPort());
		System.out.println("ref="+glut.getRef());
	}
}

2、使用TCP套接字读取服务器端文件,并在控制台打印输出。
代码:

package 实验七;
import java.awt.BorderLayout;
import java.awt.TextArea;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JTextArea;
public class Myclient extends JFrame{
	//输入框
		JTextField tf=new JTextField();
		//接收显示框
		TextArea ta=new TextArea();
		//接收消息和发送信息
		private InputStream in;
		private OutputStream out;
		private DataOutputStream Dout;
		private DataInputStream Din;
		public Myclient() {
			//设置布局风格上下型
			this.add(ta,BorderLayout.NORTH);
			this.add(tf,BorderLayout.CENTER);
			//设置宽和高
			this.setSize(500,300);
			//设置标题
			this.setTitle("这是客户端");
			//设置显示位置
			this.setLocation(500,200);
			//设置文本区和文本行的宽高
			this.setResizable(false);
			this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			this.setVisible(true);
			//吸纳建立连接,并准备好发送和接收信息的操作
			connection();
			//发送信息
			tf.addActionListener(new PostInformation());
			//开启多线程接收信息
			new Thread(new getReceive()).start();
		}
		public void connection() {
			try {
				Socket clientSocket=new Socket("localhost",1234);
				System.out.println("客户端已经创建连接");
				//准备接收信息
				in=clientSocket.getInputStream();
				Din=new DataInputStream(in);
				//准备发送信息
				out=clientSocket.getOutputStream();
				Dout=new DataOutputStream(out);
			}catch(Exception e) {
				e.printStackTrace();
			}
		}
		//通过键盘监听事件发送信息到服务器
		public class PostInformation implements ActionListener{
			@Override
			public void actionPerformed(ActionEvent e) {
				String content=tf.getText();
				//清空输入框,即设置输入为空
				tf.setText("");
				try {
					Dout.writeUTF(content);
				}catch(IOException e1) {
					try {
						Dout.close();
						out.close();
					}catch(IOException e2) {
						e2.printStackTrace();
					}
				}
			}
		}
		//开启多线程接受信息,防止一个线程阻塞导致程序崩溃
		public class getReceive implements Runnable{
			@Override
			public void run() {
				while(true) {
					try {
						String content;
						content=Din.readUTF();
						//获取本地计算机名称
						String serverName=InetAddress.getLocalHost().getHostName();
						//获得发送者IP
						InetAddress myServer=InetAddress.getByName(serverName);
						String getIPs=myServer.getHostAddress();
						//显示月-日-时-秒-星期-上午或者下午
						SimpleDateFormat sd=new SimpleDateFormat("MM-dd HH:mm:ss E a");
						//在文本区显示接收的信息
						//ta.gatText()是上次发送的内容
						ta.setText(ta.getText()+"\n"+getIPs+"\n"+sd.format(new Date())+"\n"+content+"\n");
					}catch(Exception e) {
						try {
							Din.close();
							in.close();
						}catch(Exception b) {
							
						}
					}
				}
			}
		}
	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		new Myclient();
	}

}
package 实验七;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class ManyClientServers {
	private InputStream sin;
	private OutputStream sout;
	private DataInputStream Din;
	private DataOutputStream Dout;
	//接收多个客户端的内容
	static List<Client> cs=new ArrayList<Client>();
	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		ServerSocket server;
		try {
			server=new ServerSocket(1234);
			System.out.println("服务器准备开启");
			while(true) {
				Socket s;
				s=server.accept();
				System.out.println("服务器开启准备接收信息");
				Client c=new Client(s);
				new Thread(c).start();
				cs.add(c);
			}
		}catch(IOException e) {
			e.printStackTrace();
		}
	}
	//开启多线程防止该线程阻塞。程序崩溃
	public static class Client implements Runnable{
		Socket s;
		InputStream in;
		OutputStream out;
		DataOutputStream Dout;
		DataInputStream Din;
		public Client(Socket s) {
			this.s=s;
			try {
				in=s.getInputStream();
				Din=new DataInputStream(in);
				out=s.getOutputStream();
				Dout=new DataOutputStream(out);
			}catch(IOException e) {
				e.printStackTrace();
			}
		}
		public void send(String content) {
			try {
				Dout.writeUTF(content);
			}catch(IOException e) {
				e.printStackTrace();
				try {
					Dout.close();
					out.close();
				}catch(IOException e1) {
					e1.printStackTrace();
				}
			}
		}
		@Override
		public void run() {
			while(true) {
				String content=null;
				try {
					//开启多线程防止该线程阻塞,程序崩溃
					content=Din.readUTF();
					System.out.println(content);
					//将内容立刻转发给每一个客户端
					for(Client c:cs) {
						c.send(content);
					}
				}catch(IOException e) {
					e.printStackTrace();
					try {
						Din.close();
						in.close();
					}catch(IOException e1) {
						e1.printStackTrace();
					}
				}
			}
		}
	}

}

3、实现一个命令行界面的C/S聊天室程序,服务器应包含多个线程,每个Socket对应一个线程,该线程负责读取Socket对应输入流的数据(从客户端发送过来数据),并将读到的数据向每个Socket输出流发送一次(将一个客户端发送数据“广播”到其他的客户端),提示:需要在服务器端使用List来保存所有的Socket。
代码:

package 实验七;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class MyServer {
    //定义保存所有Socket的ArrayList
    public static ArrayList<Socket> scoketList=new ArrayList<Socket>();
    public static void main(String[] args) {
        try {
            ServerSocket ss=new ServerSocket(30000);
            while (true) {
                //此代码会阻塞,将一直等待别人的连接
                Socket s=ss.accept();
                scoketList.add(s);
                //每当客户端连接后启动一条ServerThread线程为该客户端服务
                new Thread(new ServerThread(s)).start();
            }  
        } catch (IOException e) {
            e.printStackTrace();
        } 
    }
}
package 实验七;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
public class ServerThread  implements Runnable{
    //定义当前线程所处理的Socket
    Socket s=null;
    //该线程所处理Socket所对应的输入流
    BufferedReader br=null;
    public ServerThread(Socket s) throws IOException{
        this.s=s;    
        //初始化该Socket对应的输入流
        br=new BufferedReader(new InputStreamReader(s.getInputStream()));
    }
    public  void run() {
    try {
        String content=null;
        //采用循环不断从Socket中读取客户端发送过来的数据
        while((content=readFromClient())!=null){
            //遍历SocketList中的每个Socket
            //将读到的内容向每个Socket发送一次
            for(Socket s:MyServer.scoketList){
                PrintStream ps=new PrintStream(s.getOutputStream());
                ps.println(content);
            }
        }
        } catch (Exception e) {
        }
    }
    //定义读取客户端数据的方法
    private String readFromClient(){
        try {
            return br.readLine();
            //如果捕获到异常,表明该Socket对应的客户端已经关闭
        } catch (IOException e) {
            //删除该Socket
            MyServer.scoketList.remove(s);
        }
        return null;
    }
}
package 实验七;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
public class Myclient {
    public static void main(String[] args) throws Exception {
        Socket s=new Socket("127.0.0.1",30000);
        //客户端启动ClientThread线程不断读取来自服务器的数据
        new Thread(new ClientThread(s)).start();
        //获取该Socket对应的输出流
        PrintStream ps=new PrintStream(s.getOutputStream());
        String line=null;
        //不断读取键盘输入
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        while((line=br.readLine())!=null){
            if(""==line||"".equals(line.trim())){
                System.out.println("不允许发送空数据!");
            }else{
            //将用户的键盘输入内容写入Socket对应的输出流
            ps.println(line);
        }
     }
    }
}
package 实验七;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
public class ClientThread  implements Runnable{
    //该线程负责处理的Socket
    private Socket s;
    //该线程所处理的Socket所对应的输入流
    BufferedReader br=null;
    public  ClientThread(Socket s) throws IOException{
        this.s=s;
        br=new BufferedReader(new InputStreamReader(s.getInputStream()));
    }
    @Override
    public void run() {
    try {
        String content=null;
        //不断读取Socket输入流中的内容,并将这些内容打印输出
        while((content=br.readLine())!=null){
            System.out.println(content);
        }
        } catch (Exception e) {
        }
    }
}

四、心得体会:
通过此次实验,了解了如果要使网络中的两台计算机之间能够相互通信,如果从网络协议的底层去实现也许会比较困难,但是通过一些编程接口和通信模型来实现就简单得多了。知道了URL类及其WWW连接方法;学会了如何用ServerSocket和Socket类实现TCp/IP客户和服务器,以及如何用DatagramPacket和DatagramSocket进行基于UDP的网络通信;了解了如何使用MulticastSocket实现多点广播。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值