socket TCP完整应用案例


socket TCP完整应用案例_第1张图片
 

socket TCP完整应用案例_第2张图片
 
 这是一篇关于socket TCP传输的一个完整案例,出于兴趣临时用控制台模拟了一个用户的登陆 注册与文件传输

socket传输的简单模型图如下

 
socket TCP完整应用案例_第3张图片
 

在完成这个案例之前出现了几个值得关注的问题

     问题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();
		}
	}
}

你可能感兴趣的:(socket,TCPSocket)