这是一篇关于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();
}
}
}
相关推荐
本文将深入探讨C#中Socket、TCP与UDP的应用实例,并通过源代码解析其工作原理。 首先,Socket是网络通信的基础,它代表了应用程序与网络协议栈之间的接口。在C#中,Socket类是进行网络通信的核心,它可以处理TCP和...
在这个"Socket TCP应用实例"中,我们可以探讨以下几个核心知识点: 1. **Socket概念**:Socket是操作系统提供的接口,允许应用程序通过它与其他运行在相同或不同设备上的应用程序进行网络通信。在TCP/IP环境中,...
在本文中,我们将深入探讨如何在TCP协议中使用Socket进行应用实例,特别是在Qt框架下实现两个客户端之间的通信。 首先,我们需要了解Socket的基本概念。Socket可以被看作是两台计算机之间通信的端点,它包含了网络...
- SuperSocket为TCP应用提供了一套完整的事件驱动模型,如连接建立、数据接收、断开连接等,开发者只需关注这些事件的处理即可。 - 它提供了简单易用的API,如`Server.Start()`启动服务器,`Session.Send()`发送...
本资源"欧姆龙TCP UDP Socket网络通讯.zip"提供了关于如何利用TCP和UDP协议通过Socket进行欧姆龙PLC设备通信的实例。以下是关于这个主题的详细知识点: 1. **Socket基础**: - Socket是一种网络编程接口,用于在...
学习并实践这些实例,不仅可以加深对TCP和UDP协议的理解,还能掌握如何在实际项目中应用socket编程。此外,还可以学习如何处理并发连接,错误检测与恢复,以及优化网络通信性能等方面的知识。通过调试和运行这些实例...
在这个"socketTCP通信心跳包实例"中,我们主要探讨如何在Windows Forms(Winform)应用中使用Socket进行TCP通信,并通过心跳包来检测连接状态。 首先,TCP(Transmission Control Protocol)是一种面向连接的、可靠...
在.NET框架中,C#语言提供了丰富的库支持网络通信,其中Socket类是TCP/IP协议的基础。本示例将深入解析"C# Socket tcp 最简单例子源码",帮助你理解如何在C#中实现TCP(传输控制协议)客户端和服务端的通信。 首先...
在我们的“socket TCP 简单练习”中,我们将创建一个简单的TCP客户端和服务器应用。客户端会向服务器发送数据,服务器接收并响应。这个过程通常涉及以下关键步骤: 1. **创建Socket对象**:在客户端和服务器端分别...
2. 创建Socket实例:使用`new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)`创建一个Socket实例,其中`AddressFamily.InterNetwork`代表IPv4,`SocketType.Stream`表示使用TCP,`...
下面我们将详细探讨Android中如何实现Socket TCP应用,包括服务器端和客户端的开发。 1. **TCP基础知识**: - TCP是一种面向连接的协议,数据传输前需要建立连接。 - 它提供了可靠的数据传输服务,包括顺序传输、...
6. **Socket TCP封装**:为了简化编程,开发者通常会将Socket的基本操作封装成类,如`SocketTCP`。这个类可能包含初始化、连接、监听、发送、接收、关闭连接等方法,并添加必要的错误处理。 7. **C++源码**:本教程...
这个实例中的代码只是一个基础的TCP Socket通信示例,实际应用中可能需要处理更复杂的情况,如异步操作、错误处理、多线程、数据编码解码等。在进行TCP Socket编程时,要确保理解网络通信的基本原理,以及C#中的相关...
TCP Socket基于TCP协议,提供了一种标准的接口,允许应用程序进行网络通信。 在C#中,我们主要使用System.Net.Sockets命名空间中的TcpClient和TcpListener类来实现TCP客户端和服务端。`TcpClient`类用于实现客户端...
在压缩包文件"Socket&TCP实例"中,可能包含了完整的C#代码示例,包括服务器端和客户端的实现,以及如何处理不同阶段的网络交互。这些代码可以帮助你更深入地理解和应用TCP Socket编程。在实际项目中,你可以根据需求...
在《HP-Socket-通信框架开发指南.pdf》中,你将找到关于如何使用HPSocket进行TCP通信的详细教程,包括安装步骤、API详解、实例代码以及常见问题的解决方案。通过阅读这份文档,开发者可以快速掌握HPSocket的使用方法...
在这个“socket文件传输(TCP)源码实例”中,我们将深入理解如何利用TCP协议通过socket进行文件传输。TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议,确保了数据的...
总结起来,这个项目提供了一个使用QT5.1和Winsock在Windows 32位系统上实现TCPsocket通信的实例,对于学习和理解如何在QT环境下编写TCP客户端和服务器程序具有很好的参考价值。通过阅读代码、注释和实践,开发者可以...
在C#中,我们通常使用`System.Net.Sockets`命名空间中的`Socket`类来处理TCP通信。 **TCP Socket通信基础** 1. **创建服务器端** - 首先,服务器需要监听特定的IP地址和端口号。在C#中,可以通过`Socket`类的`...