java----网络编程

网络编程
练习:上传图片。
客户端
1.建立端点。
2.读取客户端已有的图片数据。
3.通过Socket输出流将数据发给服务端。
4.读取服务端反馈信息。
5.关闭。
import java.net.*;
import java.io.*;
class Demo2
{
	public static void main(String []args) throws Exception{
		Socket s = new Socket(InetAddress.getByName("192.168.0.102"),10001);
		BufferedInputStream bis = new BufferedInputStream(new FileInputStream("1.jpg"));
		BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream());
		byte[] buf = new byte[1024];
		int len = 0;
		while((len = bis.read(buf))!=-1){
			bos.write(buf,0,len);
			bos.flush();
		}
		s.shutdownOutput();
		BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
		String line = null;
		while((line = br.readLine())!=null){
			System.out.println(line);
		}
		bis.close();
		s.close();
	}
}
服务端
import java.net.*;
import java.io.*;
class Demo2
{
	public static void main(String []args) throws Exception{
		ServerSocket ss = new ServerSocket(10001);
		Socket s = ss.accept();
		String ip = s.getInetAddress().getHostAddress();
		System.out.println(ip+"....连接成功");
		int count = 1;
		BufferedInputStream bis = new BufferedInputStream(s.getInputStream());
		BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("2.jpg"));
		byte[] buf = new byte[1024];
		int len = 0;
		while((len = bis.read(buf))!=-1){
			bos.write(buf,0,len);
			bos.flush();
		}
		PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
		pw.println("上传成功");
		bos.close();
		s.close();
	}
}

分析:这个服务端有个局限性,当A客户端连接上以后,被服务端获取到,服务端就执行具体流程。这时B客户端连接,只有等待。因为服务端还没有处理完A客户端的请求,还没有循环回来执行下一次accept方法,所以暂时获取不到B客户端对象。
解决:那么,为了可以让多个客户端同时并发访问服务端,就要将每个客户端封装到一个单独的线程中。这样就可以同时处理多个客户端请求了。
疑问如何定义线程呢?
:只要明确了每一个客户端要在服务端执行的代码即可。将该代码存入run方法中。
服务端优化:
import java.net.*;
import java.io.*;
class Demo2
{
	public static void main(String []args) throws Exception{
		ServerSocket ss = new ServerSocket(10001);
		while(true){
			Socket s = ss.accept();
			new Thread(new UpLoad(s)).start();
		}
	}
}
class UpLoad implements Runnable
{
	private Socket s;
	UpLoad(Socket s){
		this.s = s;
	}
	public void run(){
		try{
			String ip = s.getInetAddress().getHostAddress();
			System.out.println(ip+"....连接成功");

			//避免覆盖之前的文件
			int count = 1;
			File file = new File(ip+".jpg");
			while(file.exists()){
				file = new File(ip+"("+(count++)+")"+".jpg");
			}

			BufferedInputStream bis = new BufferedInputStream(s.getInputStream());
			BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
			byte[] buf = new byte[1024];
			int len = 0;
			while((len = bis.read(buf))!=-1){
				bos.write(buf,0,len);
				bos.flush();
			}
			PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
			pw.println("上传成功");
			bos.close();
			s.close();
		}
		catch(Exception e){
			throw new RuntimeException("上传失败");
		}
	}
}
客户端优化:
import java.net.*;
import java.io.*;
class Demo1
{
	public static void main(String []args) throws Exception{
		//对指定文件进行判断
		if(args.length==0){
			System.out.println("请输入有效文件。");
			return;
		}
		if(args.length!=1){
			System.out.println("请输入一个有效文件。");
			return;
		}
		if(!args[0].endsWith(".jpg")){
			System.out.println("仅支持.jpg文件。");
			return;
		}
		File file = new File(args[0]);
		if(!file.exists()&&file.isFile()){
			System.out.println("文件不存在。");
			return;
		}
		if(file.length()>1024*1024*3){
			System.out.println("文件大小超过5m。");
			return;
		}
		else
			UpLoad(args,file);
	}
	public static void UpLoad(String[] args,File file) throws Exception{
		Socket s = new Socket(InetAddress.getByName("192.168.0.102"),10001);
		BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
		BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream());
		byte[] buf = new byte[1024];
		int len = 0;
		while((len = bis.read(buf))!=-1){
			bos.write(buf,0,len);
			bos.flush();
		}
		s.shutdownOutput();
		BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
		String line = null;
		while((line = br.readLine())!=null){
			System.out.println(line);
		}
		bis.close();
		s.close();
	}
}
练习:客户端通过键盘录入用户名,服务器对这个用户名进行校验。如果存在,在服务端显示“XXX,已登录”。并在客户端显示“XXX,欢迎光临”。如果该用户不存在,则在服务端显示“XXX,尝试登陆”。并在客户端显示“XXX,该用户不存在”。最多只能登陆三次。
客户端
import java.net.*;
import java.io.*;
class Demo1
{
	public static void main(String []args) throws Exception{
		Socket s = new Socket(InetAddress.getByName("192.168.0.102"),10001);
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
		for(int x=0;x<3;x++){
			String line = br.readLine();
			if(line==null)
				break;
			pw.println(line);
			BufferedReader bufr = new BufferedReader(new InputStreamReader(s.getInputStream()));
			String str = bufr.readLine();
			System.out.println(str);
			if(str.contains("欢迎"))
				break;
		}
		br.close();
		s.close();
	}
}
服务端
import java.net.*;
import java.io.*;
class Demo2
{
	public static void main(String []args) throws Exception{
		ServerSocket ss = new ServerSocket(10001);
		while(true){
			Socket s = ss.accept();
			new Thread(new loadThread(s)).start();
		}
	}
}
class loadThread implements Runnable
{
	private Socket s;
	loadThread(Socket s){
		this.s = s;
	}
	public void run(){
		try{
			String ip = s.getInetAddress().getHostAddress();
			System.out.println(ip+"....连接成功");
			BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream

()));
			boolean flag = false;
			String name = null;
			for(int x=0;x<3;x++){
				name = br.readLine();
				if(name == null)
					break;
				String uname = null;
				BufferedReader bru = new BufferedReader(new FileReader("user.txt"));
				while((uname = bru.readLine())!=null){
					if(uname.equals(name)){
						flag = true;
						break;
					}
					else
						flag = false;
				}
				PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
				if(flag){
					System.out.println(name+",已登录");
					pw.println(name+",欢迎光临");
					break;
				}
				else{
					System.out.println(name+",尝试登陆");
					pw.println(name+",该用户不存在");				
				}
			}
			br.close();
			s.close();
		}
		catch(Exception e){
			throw new RuntimeException("校验失败");
		}
	}
}
练习:客户端和服务端
1.客户端:浏览器。
2.服务端:自定义。
服务端
import java.net.*;
import java.io.*;
class Demo1
{
	public static void main(String []args) throws Exception{
		ServerSocket ss = new ServerSocket(10001);
		Socket s = ss.accept();
		String ip = s.getInetAddress().getHostAddress();
		System.out.println(ip+"....连接成功");
		OutputStream out = s.getOutputStream();
		out.write("客户端你好".getBytes());
		s.close();
	}
}

练习:查看浏览器给服务端发的东西
import java.net.*;
import java.io.*;
class Demo1
{
	public static void main(String []args) throws Exception{
		ServerSocket ss = new ServerSocket(10001);
		Socket s = ss.accept();
		String ip = s.getInetAddress().getHostAddress();
		System.out.println(ip+"....连接成功");
		InputStream in = s.getInputStream();
		byte[] buf = new byte[1024];
		int len = in.read(buf);
		System.out.println(new String(buf,0,len));
		OutputStream out = s.getOutputStream();
		out.write("客户端你好".getBytes());
		s.close();
	}
}


分析:服务端收到浏览器发来的http请求消息头。

:空行必须要有,因为要用于区分数据体和数据头。
练习:模拟浏览器向Tomcat服务器获取数据。
import java.net.*;
import java.io.*;
class Demo1
{
	public static void main(String []args) throws Exception{
		Socket s = new Socket(InetAddress.getByName("192.168.0.102"),8080);
		PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
		pw.println("GET /myweb/index.html HTTP/1.1");
		pw.println("Accept:*/*");
		pw.println("Accept-Language: zh-CN");
		pw.println("Host: 192.168.0.102:8080");
		pw.println("Connection: Keep-Close");
		pw.println();
		pw.println();
		InputStream in = s.getInputStream();
		byte[] buf = new byte[1024];
		int len = 0;
		while((len = in.read(buf))!=-1){
			System.out.println(new String(buf,0,len));
		}
	}
}

:上面部分是应答消息头
URL:统一资源定位符。可以自动截取字符串。
例:
import java.net.*;
import java.io.*;
class Demo
{
	public static void main(String []args) throws Exception{
		URL url = new URL("http://localhost:8080/myweb/index.html?name=haha&age=30");
		//获取主机
		String host = url.getHost();
		//获取端口
		int port = url.getPort();
		//获取路径
		String path = url.getPath();
		//获取文件名
		String file = url.getFile();
		//获取参数
		String query = url.getQuery();

		System.out.println("Host:"+host);
		System.out.println("Port:"+port);
		System.out.println("Path:"+path);
		System.out.println("File:"+file);
		System.out.println("Queryt:"+query);
	}
}

还可以直接进行连接,不用关闭资源。
import java.net.*;
import java.io.*;
class Demo
{
	public static void main(String []args) throws Exception{
		URL url = new URL("http://localhost:8080/myweb/index.html");
		URLConnection conn = url.openConnection();
		InputStream in = conn.getInputStream();
		byte[] buf = new byte[1024];
		int len = 0;
		while((len = in.read(buf))!=-1){
			System.out.println(new String(buf,0,len));
		}
	}
}

URL是应用层,Socket是传输层。所以用URL连接对象不会出现多余的应答消息头。
URI:功能比URL强大,例:条形码。
练习IE图形化界面。
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
class DemoIE
{
	private Frame f;
	private TextField tf;
	private Button b;
	private TextArea ta;
	private Dialog d;
	private Label l;
	DemoIE(){
		init();
	}
	public void init(){
		f = new Frame("MyIE");
		f.setBounds(400,150,700,500);
		f.setLayout(new FlowLayout());

		tf = new TextField(70);
		f.add(tf);

		b = new Button("转到");
		f.add(b);

		ta = new TextArea();
		ta.setRows(26);
		ta.setColumns(78);
		f.add(ta);

		d = new Dialog(f,"提示");
		d.setBounds(500,300,300,100);
		d.setLayout(new FlowLayout());

		f.setVisible(true);
		myEvent();
	}
	public void myEvent(){
		f.addWindowListener(new WindowAdapter(){
			public void windowClosing(WindowEvent e){
				System.exit(0);
			}
		});
		tf.addKeyListener(new KeyAdapter(){
			public void keyPressed(KeyEvent e){
				if(e.getKeyCode()==KeyEvent.VK_ENTER){
					load();
				}
			}
		});
		b.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				load();
			}
		});
	}
	public void load(){
		ta.setText("");
		try{
			String str = "http://"+tf.getText();
			URL url = new URL(new String(str));
			String host = url.getHost();
			int port = url.getPort();
			if(port == -1)
				port = 80;
			String file = url.getFile();
			System.out.println("http://"+host+":"+port+"//"+file);
			url = new URL("http://"+host+":"+port+"//"+file);
			URLConnection conn = url.openConnection();
			BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream

()));
			String line = null;
			while((line = br.readLine())!=null){
				ta.append(line+"\r\n");
			}
		}
		catch(Exception e){
			System.out.println("nono");
		}
	}
	public void showDia(String info){
		l.setText(info);
		d.setVisible(true);
	}
	public static void main(String []args){
		new DemoIE();
	}
}

知识补充
java.net.SocketAddress
|—java.net.InetSocketAddress:封装了地址和端口。

DatagramSocket(SocketAddress bindaddr) 
          创建数据报套接字,将其绑定到指定的本地套接字地址。
ServerSocket
ServerSocket(int port, int backlog) 
          利用指定的 backlog 创建服务器套接字并将其绑定到指定的本地端口号。 
ServerSocket(int port, int backlog, InetAddress bindAddr) 
          使用指定的端口、侦听 backlog 和要绑定到的本地 IP 地址创建服务器。 
backlog:队列的最大长度。指能连接到服务器的最大连接数
浏览器的动作
解析:当输入完地址回车以后,浏览器会先从本地计算机上解析目标IP,这个IP收录在C:\Windows\System32\drivers\etc\hosts中。如果没有,才会到DNS服务器中去寻找。然后会返回一个ip地址给浏览器,这样浏览器就能通过ip地址找到相应的主页了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值