您的位置:首页 > 理论基础 > 计算机网络

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();
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐