socket TCP完整应用案例
2015-07-26 22:00
369 查看
这是一篇关于socket TCP传输的一个完整案例,出于兴趣临时用控制台模拟了一个用户的登陆 注册与文件传输
socket传输的简单模型图如下
在完成这个案例之前出现了几个值得关注的问题
问题1:文件流不能被序列化 怎么将文件 文件的名字.....等等需要传递的数据从客户端传输给服务器端
问题2:怎么解决一个服务器多个客户端的问题
问题3:为什么服务器端只能接收一次客户端的请求,(服务器端与客户端不能连续的交互)
问题4:怎么判断客户端已经断开连接
问题5::服务器端的socket与客户端的socket应该何时去关闭
答案全在代码里边,由于只是做了一个demo 没有将代码封装到极致,有兴趣的小伙伴可以把代码抽离出来进行具体的封装 废话不多说 直接上代码哈
两个实体对象 分别是文件对象与用户对象
package com.javase.socket.obj; import java.io.Serializable; public class SocketUser implements Serializable { /** * 序列化标识 */ private static final long serialVersionUID = 1L; //用户名 private String username; //用户密码 private String password; //逻辑删除标识 private Integer isDelete; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Integer getIsDelete() { return isDelete; } public void setIsDelete(Integer isDelete) { this.isDelete = isDelete; } } package com.javase.socket.obj; import java.io.File; import java.io.Serializable; public class SocketFile implements Serializable{ /** * 序列化标识 */ private static final long serialVersionUID = 1L; /** *文件的名字 */ private String fileName; /** *文件的标识 */ private String fileId; /** *文件的路径 */ private String filePath; /** *客户端的文件 */ private File file; public String getFileName() { return fileName; } public void setFileName(String fileName) { this.fileName = fileName; } public String getFileId() { return fileId; } public void setFileId(String fileId) { this.fileId = fileId; } public String getFilePath() { return filePath; } public void setFilePath(String filePath) { this.filePath = filePath; } public File getFile() { return file; } public void setFile(File file) { this.file = file; } }
socket 服务端代码 package com.javase.socket.obj; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.HashMap; import java.util.Map; public class SocketFileServer extends Thread { // 定义socket 连接对象 private Socket socket = null; // 定义字节输入流 private ObjectInputStream in = null; // 定义自己输出 private ObjectOutputStream out = null; // 打印流对象 // 定义字符输入缓冲流 // 定义自负输入缓冲流 public SocketFileServer() { } public SocketFileServer(Socket socket) { this.socket = socket; } @SuppressWarnings("unchecked") @Override public void run() { boolean done = true; //while循环会一直等待客户端的请求信息 如果客户端断开连接 则退出 while(done){ try { //如果抛出异常代表客户端已经断开连接 socket.sendUrgentData(0); } catch (IOException e1) { done = false; e1.printStackTrace(); throw new RuntimeException("客户端已经断开连接.............."); } Map<String,Object> mapReceive = new HashMap<String,Object>(); try { // 通过socket 获取字节输入流 in = new ObjectInputStream(new BufferedInputStream(socket.getInputStream())); //读取一个map对象 mapReceive = (Map<String, Object>) in.readObject(); if(null != mapReceive){ Integer flag = Integer.parseInt(mapReceive.get("flag")+""); System.out.println("服务器接收的服务标志为flag=="+flag); switch (flag) { case 1: login(mapReceive); break; case 2: break; case 3: fileTransfers(mapReceive); break; default: break; } }else{ throw new RuntimeException("服务器接收的数据为null"); } } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } try { in.close(); out.close(); socket.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** *模拟用户的登陆 *@param Map<String,Object> mapReceive 接收客户端传递的map对象 */ public void login(Map<String,Object> mapReceive) throws IOException{ Map<String,Object> mapSend = new HashMap<String,Object>(); SocketUser user = null; SocketUser userSend= null; user = (SocketUser) mapReceive.get("user"); if("xiaobai".equals(user.getUsername()) && "123456".equals(user.getPassword())){ userSend = new SocketUser(); userSend.setPassword("123456"); userSend.setUsername("xupengfei"); } mapSend.put("user", userSend); //响应客户端 out = new ObjectOutputStream(socket.getOutputStream()); out.writeObject(mapSend); out.flush(); } public void reg(){ System.out.println("sorry 注册暂未编写 但不影响程序运行....."); } /** * 文件的传输服务 * @param Map<String,Object> mapReceive 接收客户端传递的map对象 */ public void fileTransfers(Map<String,Object> mapReceive) throws IOException{ Map<String,Object> mapSend = new HashMap<String,Object>(); FileOutputStream fileOut = null; FileInputStream fileInputStream = null; SocketFile inOutb =(SocketFile) mapReceive.get("file"); if(null != inOutb){ //先讲客户端传过来的文件传入upload 文件夹 String fileName =inOutb.getFileName(); fileOut = new FileOutputStream("d:\\upload\\"+fileName); fileInputStream = new FileInputStream(inOutb.getFile()); byte[] buf = new byte[fileInputStream.available()]; fileInputStream.read(buf); fileOut.write(buf); fileOut.close(); fileInputStream.close(); //响应客户端 mapSend.put("flag", 1); out = new ObjectOutputStream(socket.getOutputStream()); out.writeObject(mapSend); out.flush(); } } public static void main(String[] args) { try { //创建一个serverSocket 连接对象 ServerSocket serverSocket = new ServerSocket(8090); SocketFileServer threadSocket = null; Socket socket = null; System.out.println("服务器已经启动........"); while(true){ //接收客户端请求 socket = serverSocket.accept(); threadSocket = new SocketFileServer(socket); //设置线程的优先级 一定要设置(会影响服务器端与客户端的传输速度) threadSocket.setPriority(4); threadSocket.start(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
socket 客户端代码 package com.javase.socket.obj; import java.io.BufferedInputStream; import java.io.File; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.net.Socket; import java.net.UnknownHostException; import java.util.HashMap; import java.util.Map; import java.util.Scanner; public class SocketFileClient extends Thread{ // 定义socket 连接对象 private Socket socket = null; // 定义对象输入流 private ObjectInputStream in = null; // 定义对象输出流 private ObjectOutputStream out = null; private Scanner scanner = null; private SocketUser user = null; public SocketFileClient() { } public SocketFileClient(Socket socket) { this.socket = socket; } public void run() { scanner = new Scanner(System.in); System.out.println("**************请选择服务项目:************"); System.out.println("用户登录:请输入【1】"); System.out.println("用户注册:请输入【2】"); System.out.println("传输文件:请输入【3】"); String serviceFlag = null; //选择服务项目的标识 serviceFlag = scanner.next(); //判断是否是整数 boolean result=serviceFlag.matches("[0-9]+"); while(!result){ System.out.println("请输入一个整数..."); serviceFlag = scanner.next(); result=serviceFlag.matches("[0-9]+"); } int flag = Integer.parseInt(serviceFlag); switch (flag) { case 1: try { login(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } break; case 2: regis(); break; case 3: try { fileTransfers(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } break; default: break; } } /** * 用户登录 * @throws IOException * @throws ClassNotFoundException * */ @SuppressWarnings("unchecked") public void login() throws IOException, ClassNotFoundException { Map<String,Object> mapSend = new HashMap<String,Object>(); Map<String,Object> mapReceive = new HashMap<String,Object>(); SocketUser socketUser = new SocketUser(); System.out.print("请输入用户名:"); String username = scanner.next(); System.out.println(); System.out.print("请输入密码:"); String password = scanner.next(); socketUser.setUsername(username); socketUser.setPassword(password); mapSend.put("user", socketUser); mapSend.put("flag", 1); // 获取输出流 out = new ObjectOutputStream(socket.getOutputStream()); out.writeObject(mapSend); out.flush(); //接收服务器响应 in = new ObjectInputStream(socket.getInputStream()); mapReceive = (Map<String, Object>) in.readObject(); if(null != mapReceive){ user = (SocketUser)mapReceive.get("user"); if(null != user &&!"".equals(user)){ System.out.println( "登陆成功........"); fileTransfers(); }else{ System.out.println("您输出的用户名密码有误,返回主菜单请输入【exit】,重新登陆请按任意键........"); String tempFlag = scanner.next(); if("exit".equals(tempFlag)) run(); else login(); } } } /** * 用户注册 * */ public void regis(){ } /** * 文件传输 * @throws ClassNotFoundException * */ @SuppressWarnings("unchecked") public void fileTransfers() throws IOException, ClassNotFoundException{ //定义客户端与服务端传输的对象为Map Map<String,Object> mapSend = new HashMap<String,Object>(); Map<String,Object> mapReceive = new HashMap<String,Object>(); if(null != user){ System.out.println("请输入本机文件的绝对路径: .........(如 d:\\a.txt)"); String path = scanner.next(); File file = null; file = new File(path); while(!file.exists()){ System.out.println("该文件不存在,请重新输入......"); path = scanner.next(); file = new File(path); } SocketFile scoketFile = new SocketFile(); scoketFile.setFileName(file.getName()); scoketFile.setFilePath(file.getAbsolutePath()); scoketFile.setFile(file); mapSend.put("file", scoketFile); mapSend.put("flag", 3); // 获取输出流 out = new ObjectOutputStream(socket.getOutputStream()); out.writeObject(mapSend); out.flush(); //获取服务器响应 in = new ObjectInputStream(new BufferedInputStream(socket.getInputStream())); mapReceive = (Map<String, Object>) in.readObject(); if(null != mapReceive){ if("1".equals(mapReceive.get("flag")+"")){ System.out.println("文件传输成功,返回主菜单请安任意键......"); scanner.next(); run(); }else{ System.out.println("文件传输失败,返回主菜单请输入【exit】,重新传输文件请安任意键......"); String flag = scanner.next(); if("exit".equals(flag)) run(); else fileTransfers(); } }else{ throw new RuntimeException("接收服务器的数据不存在"); } }else{ System.out.println("您还没有登陆....请先登陆"); login(); } } public static void main(String[] args) { try { Socket socket = new Socket("localhost", 8090); // String path = "d:\\a.txt"; SocketFileClient client = new SocketFileClient(socket); System.out.println("**************客户端已经启动*****************"); client.setPriority(4); client.start(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
相关文章推荐
- Linux 下socket通信终极指南(附TCP、UDP完整代码)
- web开发 php之 socket(TCP/IP)原理 学习、理解和应用
- python网络编程之udp 与 tcpsocket的应用
- JAVA TCP/IP Socket通信机制以及应用
- Python应用-[用Python实现一个socket echo程序 && tcp socket的几个关闭状态]
- Java系列讲座一:TCP方式Socket通信案例讲解
- C#TCP/IP网络应用开发包SocketWrench .NET详细介绍
- 关于socket应用:一个不断监听一个进程的服务器以及发送信息的客户端 TCP的三次握手和四次挥手
- 网络层、传输层、应用层、端口通信协议编程接口 - http,socket,tcp/ip 网络传输与通讯知识总结
- socket 编程入门教程(一)TCP server 端:8、本章的完整源代码
- Java中Socket应用——TCP和UDP编程
- Android 手机应用开发经验 之 通过Socket(TCP/IP)与PC通讯
- 移动网络应用开发中,使用 HTTP 协议比起使用 socket 实现基于 TCP 的自定义协议有哪些优势?
- Socket编程:之TCP案例
- 跟着百度学PHP[14]-COOKIE的应用/网站登陆案例完整案例
- socket 编程入门教程(一)TCP server 端:8、本章的完整源代码
- Java Socket应用(五)——编程实现基于 TCP 的 Socket 通信
- 门面模式的典型应用 Socket 和 Http(post,get)、TCP/IP 协议的关系总结
- IP地址,TCP/UDP通讯协议概述,Socket,UDP传输,多线程UDP聊天应用
- 【原创】《Linux高级程序设计》杨宗德著 - TCP高级应用 - socket文件描述符属性控制 分类: Linux --- 应用程序设计 2014-12-06 10:26 61人阅读 评论(0) 收藏