黑马程序员_Java基础第24天_Java网络编程续
2011-10-07 11:04
477 查看
-----------------
Java培训
Android培训 期待与您的交流----------------------------
下面来完成一个传上传图片,这和前面的上传文件没有什么区别.只不过操作文件的时候使用的流对象是字节流而已! 我们来体验一下!
我们知道这是单线程,一次只能服务一个客户端.当客户端A连接后,被服务器端获取到,服务器执行具体流程,这时B客户端连接,只能等待,因为服务器的端还没有处理完客户端A的请求,如果很多客户端都要和我这个服务器通讯的话,怎么办呢?最好服务器端将每个客户端封装到不同的线程里,这样就可以处理多个客户端请求.
现在我们来实现一下,多个客户端实现文件上传.
现在就可以对多个客户端服务了,看服务端的代码,while(true)说明服务器是一直开着的,
又因为accept是阻塞式方法,当没有客户端请求服务器时,服务器一直处于阻塞状态,直到有客户端请求,如果有多个客户端访问,也会创建一个新线程为该客户端服务,因为服务器处理代码已经封装到了run()方法里面去了!
现在实现一个与上面程序类似的小程序,-----TCP 客户端并发登录
每次看完老师写完代码,自己独立写出来,一开始总是报一些错误,只要自己仔细的分析,问题还是可以解决的,如果老师些一行你写一行我觉得这样的效果不好,自己只是,照着他实现了一遍,在脑里面的印象不是特别的深,如果自己独立写出来,虽然可能耗费几倍的时间,但是已经融入了自己的理解,也提高了自己解决问题的能力.当自己写完了,再和老师的对照,然后比较那个更好一些!
用户信息如下所示:
我们写了这么多的客户端与服务端,程序不管是多线程还是单线程,它的总体思想是不变的,他们都是和流一起使用的,管服务器多么复杂,基本的原理还是这样的
学好这些,有助于我们以后理解学习和使用服务器如Tomcat等web服务器!
-----------------
Java培训 Android培训 期待与您的交流----------------------------
Java培训
Android培训 期待与您的交流----------------------------
下面来完成一个传上传图片,这和前面的上传文件没有什么区别.只不过操作文件的时候使用的流对象是字节流而已! 我们来体验一下!
//服务器端 public class TcpImage { public static void main(String[] args) throws Exception { ServerSocket server = new ServerSocket(10909); Socket client = server.accept(); // 获取客户端的输入流 InputStream is = client.getInputStream(); // 获取客户端的输出流 OutputStream out = client.getOutputStream(); // 文件存放的位置 OutputStream os = new FileOutputStream("server.jpg"); byte[] buffer = new byte[1024]; int len = 0; while ((len = is.read(buffer)) != -1) { os.write(buffer, 0, len); } // 反馈信息给客户端 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out)); bw.write("图片上传完成"); bw.flush(); os.close(); client.close(); server.close(); } }
// 客户端 class Client { public static void main(String[] args) throws Exception { // 创建客户端服务对象 Socket socket = new Socket("192.168.1.102", 10909); InputStream in = new FileInputStream("D:\\imagetest\\desk.jpg"); // 获取客户端的输出流对象 OutputStream os = socket.getOutputStream(); // 获取客户端的输入流对象 InputStream is = socket.getInputStream(); byte[] buffIn = new byte[1024]; int len = 0; while ((len = in.read(buffIn)) != -1) { os.write(buffIn, 0, len); } // 告诉服务器我已经发送完毕 socket.shutdownOutput(); BufferedReader br = new BufferedReader(new InputStreamReader(is)); String message = br.readLine(); System.out.println(message); in.close(); socket.close(); } }
我们知道这是单线程,一次只能服务一个客户端.当客户端A连接后,被服务器端获取到,服务器执行具体流程,这时B客户端连接,只能等待,因为服务器的端还没有处理完客户端A的请求,如果很多客户端都要和我这个服务器通讯的话,怎么办呢?最好服务器端将每个客户端封装到不同的线程里,这样就可以处理多个客户端请求.
现在我们来实现一下,多个客户端实现文件上传.
public class TcpThreads implements Runnable { private Socket socket; public TcpThreads(Socket socket) { this.socket = socket; } public void run() { int count = 1; String ip = socket.getInetAddress().getHostAddress(); try { System.out.println(ip + "............connected"); // 获取客户端的输入流 File file = new File(ip + ".jpg"); // 如果文件已经存在,则修改名称使之加一,直到名称不等 while (file.exists()) file = new File(ip + "(" + (count++) + ")" + ".jpg"); InputStream is = socket.getInputStream(); // 获取客户端的输出流 OutputStream out = socket.getOutputStream(); // 文件存放的位置 OutputStream os = new FileOutputStream(file); byte[] buffer = new byte[1024]; int len = 0; while ((len = is.read(buffer)) != -1) { os.write(buffer, 0, len); } // 反馈信息给客户端 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out)); bw.write("图片上传完成"); bw.flush(); os.close(); socket.close(); } catch (Exception e) { throw new RuntimeException(ip + "上传失败"); } } }
class ClientImage { 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; } long maxSize = 1024 * 1024 * 5; if (file.length() > maxSize) { System.out.println("文件不能大于5M"); return; } if(!file.getName().endsWith(".jpg")){ System.out.println("文件只能是JPG"); return; } // 创建客户端服务对象 Socket socket = new Socket("192.168.1.102", 12345); InputStream in = new FileInputStream(file); // 获取客户端的输出流对象 OutputStream os = socket.getOutputStream(); // 获取客户端的输入流对象 InputStream is = socket.getInputStream(); byte[] buffIn = new byte[1024]; int len = 0; while ((len = in.read(buffIn)) != -1) { os.write(buffIn, 0, len); } // 告诉服务器我已经发送完毕 socket.shutdownOutput(); BufferedReader br = new BufferedReader(new InputStreamReader(is)); String message = br.readLine(); System.out.println(message); in.close(); socket.close(); } }
class ServerImage { public static void main(String[] args) throws Exception { ServerSocket server = new ServerSocket(12345); while (true) { Socket socket = server.accept();// 阻塞式方法,当获取到客户端对象,就创建线程 new Thread(new TcpThreads(socket)).start(); } } }
现在就可以对多个客户端服务了,看服务端的代码,while(true)说明服务器是一直开着的,
public static void main(String[] args) throws Exception { ServerSocket server = new ServerSocket(12345); while (true) { Socket socket = server.accept();// 阻塞式方法,当获取到客户端对象,就创建线程 new Thread(new TcpThreads(socket)).start(); } }
又因为accept是阻塞式方法,当没有客户端请求服务器时,服务器一直处于阻塞状态,直到有客户端请求,如果有多个客户端访问,也会创建一个新线程为该客户端服务,因为服务器处理代码已经封装到了run()方法里面去了!
现在实现一个与上面程序类似的小程序,-----TCP 客户端并发登录
每次看完老师写完代码,自己独立写出来,一开始总是报一些错误,只要自己仔细的分析,问题还是可以解决的,如果老师些一行你写一行我觉得这样的效果不好,自己只是,照着他实现了一遍,在脑里面的印象不是特别的深,如果自己独立写出来,虽然可能耗费几倍的时间,但是已经融入了自己的理解,也提高了自己解决问题的能力.当自己写完了,再和老师的对照,然后比较那个更好一些!
class ServerLogon implements Runnable { private Socket socket; public ServerLogon(Socket socket) { this.socket = socket; } public void run() { String ip = socket.getInetAddress().getHostAddress(); try { //打印客户端的ip System.out.println(ip + "............. connected!"); BufferedReader br = new BufferedReader(new InputStreamReader(socket .getInputStream())); PrintWriter pw = new PrintWriter(socket.getOutputStream(), true); // 只有三次尝试的机会 for (int i = 0; i < 3; i++) { BufferedReader reader = new BufferedReader(new InputStreamReader( new FileInputStream("user.txt"))); String username = br.readLine(); //如果用户直接退出 if (username == null) { break; } String line = null; boolean flag = false; while ((line = reader.readLine()) != null) { if (line.equals(username)) { flag = true; break; } } //如果用户名相同 if (flag) { System.out.println(username + "登录成功"); pw.println("欢迎登录"); }else { System.out.println(username + "尝试登录"); pw.println("无效的用户名"); } reader.close(); } socket.close(); } catch (IOException e) { throw new RuntimeException(ip + "连接失败"); } } }
class UserClient { public static void main(String[] args) throws Exception { Socket socket = new Socket("192.168.1.102", 11111); PrintWriter bw = new PrintWriter(socket.getOutputStream(), true); BufferedReader in = new BufferedReader(new InputStreamReader(socket .getInputStream())); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); for (int i = 0; i < 3; i++) { String name = br.readLine(); System.out.println(name); //如果客户端按Ctrl+c if (name == null) break; bw.println(name); String message = in.readLine(); System.out.println(message); if (message.contains("欢迎")) { break; } } br.close(); socket.close(); } }
public class TcpLogon { public static void main(String[] args) throws IOException { ServerSocket server = new ServerSocket(11111); while (true) { Socket socket = server.accept(); new Thread(new ServerLogon(socket)).start(); } } }
用户信息如下所示:
我们写了这么多的客户端与服务端,程序不管是多线程还是单线程,它的总体思想是不变的,他们都是和流一起使用的,管服务器多么复杂,基本的原理还是这样的
学好这些,有助于我们以后理解学习和使用服务器如Tomcat等web服务器!
-----------------
Java培训 Android培训 期待与您的交流----------------------------
相关文章推荐
- 黑马程序员---Java基础--24天(网络编程之二)
- 黑马程序员--Java基础--GUI、网络编程
- 黑马程序员—JAVA基础之网络编程
- 黑马程序员 Java基础--网络编程
- 黑马程序员—JAVA基础—网络编程
- 黑马程序员 4000 ——Java基础---网络编程
- 黑马程序员_Java基础_网络编程
- 黑马程序员 java基础之网络编程
- 『黑马程序员』---java--网络编程--TCP基础
- Java基础24天--03--网络编程(TCP--客户端并发登陆)
- 黑马程序员——Java基础---网络编程
- 黑马程序员_java基础笔记(08)...GUI,网络编程,正则表达式
- 黑马程序员——Java网络编程基础
- 黑马程序员-----Java基础-----网络编程
- 黑马程序员——java基础_网络编程
- 黑马程序员----JAVA基础----网络编程
- 黑马程序员_java基础-网络编程
- 黑马程序员_毕向东_Java基础_DAY23-24_网络编程
- 黑马程序员--java 基础之网络编程 --09
- 黑马程序员:Java基础总结----网络编程