(15)Java网络编程-应用练习篇

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------

     Java网络编程-应用练习篇

这一篇主要是一些常见应用分析和练习。

练习一:

/*
通过tcp协议,客户端上传图片给服务端,服务端将图片数据发送到指定目的(硬盘)
并给客户端返回上传成功。
分析步骤:
客户端
1,创建socket服务指定客户端点
2,读取客户端指定图片数据
3,通过socket输出流将图片数据发送服务端并定义结束标记
4,通过流对象接收服务端返回的上传信息
5,关闭流资源
服务端
1,创建ServerSocket服务端并指定端口号
2,读取客户端发送来的图片数据并存储缓冲区
3,将缓冲区里的数据写入到指定目的地
4,返回客户端上传信息
5,关闭流资源。
*/
import java.net.*;
import java.io.*;
class  PicClient{//客户端
	public static void main(String[] args) throws Exception{
		Socket s = new Socket("192.168.0.2",10006);
		//读取指定的图片
		FileInputStream fis = 
			new FileInputStream(new File("c:\\背景.jpg"));
		//Socket服务的输出流将数据发送
		OutputStream out = s.getOutputStream();
		//定义一个缓冲区
		byte[] buy = new byte[1024];
		int len = 0;
		while ((len= fis.read(buy))!=-1){
			out.write(buy,0,len);
		}
		//定义结束标记,告诉服务端数据传送完毕
		s.shutdownOutput();
		//通过socket读取流,读取服务端返回的信息
		InputStream is = s.getInputStream();
		byte[] b = new byte[1024];
		int leng = is.read(b);
		System.out.println(new String(b,0,leng));
		fis.close();
		s.close();
	}
}
class  PicServer//服务端{
	public static void main(String[] args) throws Exception{
		ServerSocket ss = new ServerSocket(10006);
		Socket s = ss.accept();
		//获取客户端iPhone地址
		String ip = s.getInetAddress().getHostAddress();
		System.out.println(ip);
		InputStream is = s.getInputStream();
		FileOutputStream fos = new FileOutputStream("c:\\复制图片.jpg");
		byte[] buy = new byte[1024];
		int len = 0;
		while ((len=is.read(buy))!=-1){
			fos.write(buy,0,len);
		}
		OutputStream os = s.getOutputStream();
		os.write("上传成功".getBytes());
		fos.close();
		s.close();
		ss.close();
	}
}


练习二:

TCP客户端并发上传图片

思考问题:

1, 通过上面的练习了解到,这是一个单线程的服务,其局限性是当a客户连接服务端后正常秩序流程,若b客户想要连接只能等待,因为服务端必须把a客户端的请求处理完才能执行b客户端的请求,所以暂时获取不到b客户端对象。

2, 若客户端发送过来的文件不是图片文件或者文件过大怎办?

解决:

1, 为了让多个客户可以同时并发访问服务端,服务端最好的方法就是把每个客户封装到单独的一个线程中,这样就可以同时处理多个客户的请求。

2, 创建文件对象,判断传送进来的文件是否符合指定规则,若不符合返回信息。

怎么定义线程呢?

只要明确了每个客户端在服务端执行的代码,将代码存入run方法即可

示例:

/*
客户端并发请求的练习
*/
import java.net.*;
import java.io.*;
class  PicClientDemo{
	public static void main(String[] args) throws Exception{
		//判断传入的值
		if(args.length!=1){
			System.out.println("请输入一个标准图片");
			return;
		}
		//创建文件对象
		File file=new File(args[0]);  
		//判断文件是否存在
		if (!(file.exists()&&file.isFile())){
			System.out.println("传入的路径错误或文件不存在或不是文件");
			return;
		}
		//判断文件是否是指定格式
		if (!(file.getName().endsWith(".jpg"))){
			System.out.println("传入的文件格式不对");
			return;
		}
		//判断文件大小
		if (file.length()>1024*1024*8){
			System.out.println("传入的文件大于8M");
			return;
		}
		Socket s = new Socket("192.168.0.2",10006);
		//读取指定的图片
		FileInputStream fis = 
			new FileInputStream(file);
		//Socket服务的输出流将数据发送
		OutputStream out = s.getOutputStream();
		//定义一个缓冲区
		byte[] buy = new byte[1024];
		int len = 0;
		while ((len= fis.read(buy))!=-1){
			out.write(buy,0,len);
		}
		//定义结束标记,告诉服务端数据传送完毕
		s.shutdownOutput();
		//通过socket读取流,读取服务端返回的信息
		InputStream is = s.getInputStream();
		byte[] b = new byte[1024];
		int leng = is.read(b);
		System.out.println(new String(b,0,leng));
		fis.close();
		s.close();
	}
}
//利用多线程实现并发上传数据
class PicThread implements Runnable{
	private Socket s;
	PicThread(Socket s){
		this.s = s;
	}
	public void run(){
		try{		
			//获取客户端iP地址
			String ip = s.getInetAddress().getHostAddress();
			System.out.println(ip);
			InputStream is = s.getInputStream();
			int count = 1;
			//文件保存路径
			File dir = new File("c:\\");
			File file = new File(dir,"复制图片.jpg");
			//判断文件是否存在
			while (file.exists()){
				file = new File(dir,"复制图片("+(count++)+").jpg");
			}
			//将上传的数据存进指定输出流
			FileOutputStream fos = new FileOutputStream(file);
			byte[] buy = new byte[1024];
			int len = 0;
			while ((len=is.read(buy))!=-1){
				fos.write(buy,0,len);
			}
			//返回上传信息给客户端
			OutputStream os = s.getOutputStream();
			os.write("上传成功".getBytes());
			fos.close();
			s.close();
		}
		catch (Exception e){
			throw new RuntimeException("数据上传失败");
		}	
	}
}
class  PicServerDemo{
	public static void main(String[] args) throws Exception{
		//创建服务端Socket服务,监听端口
		ServerSocket ss = new ServerSocket(10006);
		//主线程循环执行或将上传的客户端数据
		while (true){	
			//获取客户端对象
			Socket s = ss.accept();
			//创建并开启客户端线程
			new Thread(new PicThread(s)).start();
		}
	}
}

练习三:

/*
练习:客户端并发登陆
客户端通过键盘录入用户名,服务端对这个用户进行校验。
若该用户存在,在服务端显示XXX,已登录;并在客户端显示XXX,欢迎光临。
若用户不存在,在服务端显示XXX,尝试登陆;
并在客户端显示XXX,该用户不存在,且最多登陆三次
*/
import java.net.*;
import java.io.*;
//客户端
class LoginClinet{
	public static void main(String[] args) throws Exception{
		//创建服务
		Socket s = new Socket("192.168.0.2",10007);
		//键盘录入
		BufferedReader bufs = 
			new BufferedReader(new InputStreamReader(System.in));
		//使用Socket的输出流将数据写入
		PrintWriter ps = new PrintWriter(s.getOutputStream(),true);
		//接收服务器返回的信息
		BufferedReader br = 
			new BufferedReader(new InputStreamReader(s.getInputStream()));
		String line = null;
		//设置登陆次数
		for (int x = 1;x<=3 ;x++ ){
			line = bufs.readLine();//获取键盘信息
			if(line==null)
				break;
			ps.println(line);//将数据发送服务端
			String info = br.readLine();//获取服务端返回信息
			System.out.println(info);
			if (info.contains("欢迎"))
				break;
		}
		bufs.close();
		s.close();
	}
}
//利用多线程实现并发登陆
class LoginThread implements Runnable{
	private Socket s;
	LoginThread(Socket s){
		this.s = s;
	}
	public void run(){
		try{
			for (int x = 1;x<=3 ;x++ )//在服务端限制登陆次数{
				//获取客户端ip地址
				String ip = s.getInetAddress().getHostAddress();
				System.out.println("客户端iP:"+ip);
				//通过socket服务读取流获取客户端发送的信息
				BufferedReader bufr = 
					new BufferedReader(new InputStreamReader(s.getInputStream()));
//关联数据库,查询是否有该客户端信息,这时自定义数据库一个文本文件内存储的是用户名
				BufferedReader in = 
					new BufferedReader(new FileReader("c:\\users.txt"));
				String line = bufr.readLine();//获取信息				
				if (line==null){
					break;//当接收的是null时退出
				}
				String data = null;
				boolean flag = false;
				while ((data= in.readLine())!=null){
					if (line.equals(data)){
						flag = true;
						break;
					}
				}
				//通过socket服务输出流,给发送客户端登陆信息
				PrintWriter ps = new PrintWriter(s.getOutputStream(),true);
				if (flag){
					ps.println(line+",欢迎光临");
					System.out.println(line+",已登录");
					break;
				}
				else{
					ps.println(line+"该用户不存在,请重新登陆");
					System.out.println(line+"尝试登录");
				}
			}
			s.close();
		}
		catch (Exception e){
			throw new RuntimeException("用户登陆失败");
		}
	}
}
//服务端
class  LoginServer{
	public static void main(String[] args) throws Exception{
		ServerSocket ss = new ServerSocket(10007);//创建服务端并监听端口;
		while (true){
			Socket s = ss.accept();//获取客户端对象
			new Thread(new LoginThread(s)).start();//创建并开启多线程
		}
	}
}
模拟数据库:


打印结果:



练习三(关于浏览器客户端显示):

/*
浏览器客户端-自定义服务端
浏览器是一个标准的客户端,它可以对服务端传输过来的数据进行解析,
把符合应用层协议的消息部分解析后,将头信息拆包,传送到应用层,
只保留正确的正文主题部分县市在客户端上。
因为java编译使用的是传输层和网际层处理数据,所以接收全部消息
并包含头消息。浏览器处于应用层,编译时将头消息编译,只留下主题信息
示例:
演示客户端和服务端
客户端:浏览器
服务端:自定义
*/
import java.net.*;
import java.io.*;
class  ServerDemo{
	public static void main(String[] args)throws Exception {
		ServerSocket ss = new ServerSocket(11000);
		Socket s = ss.accept();
		PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
		pw.println("<font color='red' size='7'>浏览器您好,我是服务端发送给您的消息。</font>");
		s.close();
		ss.close();
	}
}在浏览器输入ip地址加端口号即可显示


URL-URLConnection

概述:

类 URL 代表一个统一资源定位符,它是指向互联网“资源”的指针。资源可以是简单的文件或目录,也可以是对更为复杂的对象的引用,例如对数据库或搜索引擎的查询。

URI:范围大,条形码等也包含咋此范围内

URL:范围小即域名

常用构造方法:

//根据指定 protocolhostport号和 file 创建 URL对象。

URL(String protocol,String host,int port,String file); 

常用方法:

 String

getFile() 
          获取此 URL 的文件名。

 String

getHost() 
          获取此 URL 的主机名(如果适用)。

 String

getPath() 
          获取此 URL 的路径部分。

 int

getPort() 
          获取此 URL 的端口号。

 String

getProtocol() 
          获取此 URL 的协议名称。

 String

getQuery() 
          获取此 URL 的查询部分。


URLConnection 

抽象类 URLConnection 是所有类的超类,它代表应用程序和 URL 之间的通信链接。此类的实例可用于读取和写入此 URL 引用的资源

openConnection();//对影响到远程资源连接的参数进行操作。

 示例:

/*
需求:
自定义图形化界面浏览器即客户端
分析步骤:
1,自定义浏览器构造图形化界面
2,注册事件监听机制
3,通过创建URL对象接收服务端发送来的数据

*/
import java.net.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
class  MyIEDemo{
		//定义所需组件引用
		private Frame f;
		private Button but;
		private TextArea ta;
		private TextField tf;
		//构造函数
		MyIEDemo(){
			info();
		}
		private void info(){
			//组件实例化
			f = new Frame("我的网页窗口");
			ta = new TextArea(60,50);
			tf = new TextField(40);
			but = new Button("搜索");
			//对窗口进行设置
			f.setBounds(300,200,400,370);
			f.setLayout(new FlowLayout());
			//添加组件
			f.add(tf);
			f.add(but);
			f.add(ta);
			//事件监听
			myEvent();
			//显示窗口
			f.setVisible(true);
		}
		private void myEvent(){
			//对窗口注册关闭监听
			f.addWindowListener(new WindowAdapter(){
				public void windowClosing(WindowEvent e){
					System.exit(0);
				}
			});
			//对按钮注册活动监听
			but.addActionListener(new ActionListener(){
				public void actionPerformed(ActionEvent e){
					showFile();//若点击按钮,就会将收索的内容显示文本区
				}
			});
			//对文本框注册键盘监听
			tf.addKeyListener(new KeyAdapter(){
				public void keyPressed(KeyEvent e){
					if (e.getKeyCode()==KeyEvent.VK_ENTER)
						showFile();//若敲回车就会就会将收索的内容显示文本区
				}
			});
		}
		private void showFile(){
			//清空文本区
			ta.setText("");
			//获取键盘录入的路径
			String path = tf.getText();
			try{
/*
重点分析:这里就不用写socket,因为它已经封装进了URL里面,
并且还封装了HTTP等协议,现在就不再传输层而是在应用层。				
*/
					//将地址封装成对象
				URL url = new URL(path);
				//链接网页服务器,对远程资源连接的参数进行操作。
				URLConnection conn = url.openConnection();
				//读取流,用于读取服务器返回数据 
				InputStream in = conn.getInputStream();
				byte[] buy = new byte[1024];
				 int len=in.read(buy);    
                //将数据显示在文本区中    
                ta.append(new String(buy,0,len)); 
			}
			catch (Exception e){
				throw new RuntimeException("网络"+path+"链接失败");
			}
		}
	public static void main(String[] args) throws Exception{
		new MyIEDemo();
	}
}

网络编程-小知识点

1Socket类中空参数的构造函数

通过connect(SocketAddress endpoint)方法来连接服务器,

因为SocketAddress是一个抽象类,他的子类InetSocketAddress实现了IP套接字地址(ip+端口号)。

2,在ServerSocket构造函数:ServerSocket(int port,int backlog)

Backlog标示队列的最大长度即客户端连接服务器的个数。

1, DNS域名解析

当我们在浏览器输入如www.baidu.com主机名时浏览器是如何通过主机名获取该主机ip地址的呢?

解决:

这就需要将主机名翻译成IP地址,即域名解析:DNS

在进行访问的时候,会先在本地的hosts文件(c:\windows\system32\drivers\ect\host中找对应的映射。若有,则直接返回请求;若无,则到公网的映射列表即DNS中找对应的映射,找到后,将主机名对应的IP地址返回给本机,本机通过这个IP地址找到对应的服务器。

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------详细请查看: http://edu.csdn.net
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值