java----网络编程

来源:互联网 发布:印度 种姓 知乎 编辑:程序博客网 时间:2024/06/08 05:52
网络编程
练习:上传图片。
客户端
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;}elseUpLoad(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;}elseflag = 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地址找到相应的主页了。

原创粉丝点击