因为用swing做客户端,不能用传统的SSM框架的tomcat,要自己搞定socket,以下是我给自己挖的坑,并总结的经验
一、要用ObjectOutputStream/ObjectInputStream,这个直接传对象,意味着对象里面你想写啥就写啥,而inputStream/outputStream,无论是传int,还是传string的三次传输都是坑
二、我想当然的认为下面代码每次传输打开socket关闭流太慢,总想不关对象,重复利用,但是他的设计就是让你关掉的,于是各种报错,那段时间生无可恋,最后试了一下用完就关,发现速度很快…
其实tomcat的一次传输(request/reponse)也是用完就关的。
public void close() {
try {
if(objectInputStream!=null) {
objectInputStream.close();
}
if(inputStream!=null) {
inputStream.close();
}
if(objectOutputStream!=null) {
objectOutputStream.close();
}
if(outputStream!=null) {
outputStream.close();
}
socket.close();
System.out.println("-----------请求结束socket-------------");
} catch (IOException e) {
e.printStackTrace();
}
}
三、这个绕不开使用线程,首先线程的意思就是把事情分开做,互不打扰,所以不要往线程调度的方面考虑,相信我,那是个坑!一个县城就是一个请求,完事就销毁,速度很快
四、推送消息就是在客户端装一个微型服务器new ServerSocket(8081),只接受指定服务器IP的访问,如下
public class ClientFactory extends Thread {
public void run() {
try {
//初始化服务器
PushSocket_Client.init();
PushSocket_Client st=null;
while(true) {
Socket ss=PushSocket_Client.getSocket();
System.out.println(ss.getInetAddress());
//指定了服务器地址
if(ss.getInetAddress().toString().equals("/192.168.50.155")) {
st=new PushSocket_Client(ss);
Thread th=new Thread(st);
th.start();
}else {
ss.close();
System.out.println(“有来自非服务器的访问,已关闭该访问”);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
下面放全部代码,里面传输的都是对象,对象的模型自己随意创建,我就不放了。凡是发消息的,都是调用方法,凡是受消息的都是调用服务,逻辑在服务里面写。记住,一次请求从头跑到尾,做完一件事(增删改查),就是线程不需要管其他线程怎么做、做到哪一步了。
服务器三个文件
import java.io.IOException;
public class ServiceFactory extends Thread {
public void run() {
try {
//初始化服务器
SocketServer.init();
SocketServer st=null;
while(true) {
st=new SocketServer(SocketServer.getSocket());
Thread th=new Thread(st);
th.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.awt.EventQueue;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import com.atja.FisrtPlayer.bean.MyResponse;
import com.atja.FisrtPlayer.bean.MyRequest;
import com.atja.FisrtPlayer.service.ServerService;
import com.atja.FisrtPlayer.views.ServerPlayer;
import com.sun.jna.NativeLibrary;
import uk.co.caprica.vlcj.discovery.NativeDiscovery;
import uk.co.caprica.vlcj.runtime.RuntimeUtil;
/**
-
@author 桌面服务器,类似于servlet
-
类比于
-
application对象Map<?>
*session对象socket
*request对象
*response对象
*再做一个websocket对象需要不同的端口,实现推送
*服务器不断发送值,客户端接收,群发遍历session对象就可以,取出相关的对象发送
*/
public class SocketServer implements Runnable{
public static Map<String, InetAddress> ipMap=new HashMap<String, InetAddress>();
private static ServerSocket serverSocket=null;
private Socket socket=null;
private InputStream inputStream=null;
private OutputStream outputStream=null;
private ObjectOutputStream objectOutputStream=null;
private ObjectInputStream objectInputStream=null;
public MyRequest request;
public MyResponse response;
public static void main(String[] args){
//开启了服务器线程
ServiceFactory th=new ServiceFactory();
th.start();
//开启视频控件
//new NativeDiscovery().discover();
String filePath="";
if (RuntimeUtil.isWindows())
filePath = “D:\VLC”;
else if (RuntimeUtil.isMac())
filePath = “/Applications/VLC.app/Contents/MacOS/lib”;
else if (RuntimeUtil.isNix())
filePath = “/home/linux/vlc/install/lib”;NativeLibrary.addSearchPath(RuntimeUtil.getLibVlcLibraryName(), filePath); //开启本地界面群发控制 EventQueue.invokeLater(new Runnable() { public void run() { try { ServerPlayer frame = new ServerPlayer (); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); /*while(true) { Scanner scan = new Scanner(System.in); String read = scan.nextLine(); //创建群发消息 MyRequest request=new MyRequest(); request.setId(5); request.setMsg("服务器:这是一条群发消息"+read); //我这里是等待服务器启动,实际中不必要 try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(SocketServer.ipMap.isEmpty()); System.out.println(request); //群发,可以筛选ip发送,由于map的特性,key必须唯一,相同的Ip不会重复放入, //但是应该设置失效时间,不然map太大 for(InetAddress ip:SocketServer.ipMap.values()) { System.out.println(ip); PushSocket_Server push=new PushSocket_Server(ip,request); Thread th1=new Thread(push); th1.start(); } }*/
}
public void run() {
try {
request=(MyRequest)objectInputStream.readObject();
//调用业务逻辑层把请求响应传进去
response=ServerService.getInstance().play(request);
objectOutputStream.writeObject(response);
close();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public SocketServer(Socket socket) throws IOException {
this.socket=socket;
System.out.println("------有来自IP:"+socket.getInetAddress()+“的访问-------”);
ipMap.put("", socket.getInetAddress());
System.out.println(ipMap.isEmpty());
for(InetAddress ip:SocketServer.ipMap.values()) {
System.out.println(ip);
}System.out.println("已加入到访客列表,该身份预计失去连接(待定)分钟后失效,失效后收取不到推送消息"); inputStream=socket.getInputStream(); outputStream=socket.getOutputStream(); objectOutputStream=new ObjectOutputStream(outputStream); objectInputStream=new ObjectInputStream(inputStream);
}
public static void init() throws IOException {
serverSocket=new ServerSocket(8080);
System.out.println("-----------socket服务器初始化完毕-------------");
}
public static Socket getSocket() throws IOException {
return serverSocket.accept();
}
public void close(){
try {
if(objectInputStream!=null) {
objectInputStream.close();
}
if(inputStream!=null) {
inputStream.close();
}
if(objectOutputStream!=null) {
objectOutputStream.close();
}
if(outputStream!=null) {
outputStream.close();
}
System.out.println("------IP:"+socket.getInetAddress()+“一次通话完成-------”);
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import com.atja.FisrtPlayer.bean.MyRequest;
import com.atja.FisrtPlayer.bean.MyResponse;
/**
-
@author 推送服务器端,本质是个客户端,不能单例,需要new多个socket,传入客户端的ip地址
*需要线程来操作,充分利用服务器资源
*/
public class PushSocket_Server implements Runnable{
private int port=8081;
private Socket socket=null;
public InputStream inputStream=null;
public OutputStream outputStream=null;
public ObjectOutputStream objectOutputStream=null;
public ObjectInputStream objectInputStream=null;
public MyRequest request;
public MyResponse response;
public static void main(String[] args) {
//创建对象,信息由对象变量控制
MyRequest request=new MyRequest();
request.setId(5);
request.setMsg(“服务器:这是一条群发消息”);
//数据传输一次通话
System.out.println(request);
System.out.println(SocketServer.ipMap.isEmpty());
for(InetAddress ip:SocketServer.ipMap.values()) {
System.out.println(ip);
PushSocket_Server push=new PushSocket_Server(ip,request);
Thread th=new Thread(push);
th.start();
}
}
public void run() {
try {
outputStream=socket.getOutputStream();
inputStream=socket.getInputStream();
objectInputStream=new ObjectInputStream(inputStream);
objectOutputStream=new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(request);
response=(MyResponse) objectInputStream.readObject();
System.out.println(“来自客户端的发送成功回执:”+response);
close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}public PushSocket_Server(InetAddress ip,MyRequest request){
try {
socket =new Socket(ip,port);
this.request=request;
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("-----------服务器请求开始推送socket发消息到IP:"+ip+"-------------");
}public void close() {
try {
if(objectInputStream!=null) {
objectInputStream.close();
}
if(inputStream!=null) {
inputStream.close();
}
if(objectOutputStream!=null) {
objectOutputStream.close();
}
if(outputStream!=null) {
outputStream.close();
}
socket.close();
System.out.println("-----------服务器发送完毕,请求结束推送socket-------------");
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端三个文件
import java.io.IOException;
import java.net.Socket;
/**
- @author 客户端接收推送服务器作为一个单独的线程跑起来,接收到的数据的处理交给业务逻辑
*/
public class ClientFactory extends Thread {
public void run() {
try {
//初始化服务器
PushSocket_Client.init();
PushSocket_Client st=null;
while(true) {
Socket ss=PushSocket_Client.getSocket();
System.out.println(ss.getInetAddress());
//指定了服务器地址
if(ss.getInetAddress().toString().equals("/192.168.50.155")) {
st=new PushSocket_Client(ss);
Thread th=new Thread(st);
th.start();
}else {
ss.close();
System.out.println(“有来自非服务器的访问,已关闭该访问”);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import javax.swing.JFrame;
import com.atja.FisrtPlayer.bean.MyRequest;
import com.atja.FisrtPlayer.bean.MyResponse;
import com.atja.FisrtPlayer.bean.State;
import com.atja.FisrtPlayer.clientService.ClientPushService;
import com.atja.FisrtPlayer.clientService.ClientService;
/**
-
@author 客户端
*一次请求一次返回,不必用线程
*/
public class SocketClient{
private static SocketClient socketClient=new SocketClient();
private String ip=“192.168.50.155”;
private int port=8080;
private Socket socket=null;
public InputStream inputStream=null;
public OutputStream outputStream=null;
public ObjectOutputStream objectOutputStream=null;
public ObjectInputStream objectInputStream=null;
public MyRequest request;
public MyResponse response;
//调用小例子
public static void main(String[] args) {
//开启客户端的服务器
ClientFactory fa=new ClientFactory();
fa.start();
//初始化视频
ClientPushService.getInstance();
//创建对象,信息由对象变量控制
MyRequest request=new MyRequest();
request.setId(0);
request.setMsg(“客户端:初始化”);
//数据传输一次通话
MyResponse response=SocketClient.getInstance().setRequest(request);
MyRequest request1=ClientService.getInstance().play(response);
System.out.println(request1);
}private SocketClient(){
}
public static SocketClient getInstance() {
return socketClient;
}
public void close() {
try {
if(objectInputStream!=null) {
objectInputStream.close();
}
if(inputStream!=null) {
inputStream.close();
}
if(objectOutputStream!=null) {
objectOutputStream.close();
}
if(outputStream!=null) {
outputStream.close();
}
socket.close();
System.out.println("-----------请求结束socket-------------");
} catch (IOException e) {
e.printStackTrace();
}
}
public MyResponse setRequest(MyRequest request){
try {
socket =new Socket(ip,port);
System.out.println("-----------请求开始socket-------------");
outputStream=socket.getOutputStream();
inputStream=socket.getInputStream();
objectInputStream=new ObjectInputStream(inputStream);
objectOutputStream=new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(request);
response=(MyResponse) objectInputStream.readObject();
close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return response;
}
}
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import com.atja.FisrtPlayer.bean.MyResponse;
import com.atja.FisrtPlayer.bean.MyRequest;
import com.atja.FisrtPlayer.bean.State;
import com.atja.FisrtPlayer.clientService.ClientPushService;
import com.atja.FisrtPlayer.service.ServerService;
/**
- @author 推送客户端,微型服务器,只有一个访客,限制IP192.168.50.155
- 由于业务逻辑写死,尽量不做具体操作,只作为数据传输通道,把数据交由请求方处理
*/
public class PushSocket_Client implements Runnable{
private static ServerSocket pushServerSocket=null;
private Socket socket=null;
private InputStream inputStream=null;
private OutputStream outputStream=null;
private ObjectOutputStream objectOutputStream=null;
private ObjectInputStream objectInputStream=null;
public MyRequest request;
public MyResponse response;
public static void main(String[] args) {
//开启客户端的服务器
ClientFactory fa=new ClientFactory();
fa.start();
}
public void run() {
try {
request=(MyRequest)objectInputStream.readObject();
//调用业务逻辑层把请求响应传进去
response=ClientPushService.getInstance().play(request);
objectOutputStream.writeObject(response);
close();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public PushSocket_Client(Socket socket) throws IOException {
this.socket=socket;
System.out.println("------有来自服务器IP:"+socket.getInetAddress()+"的推送消息-------");
inputStream=socket.getInputStream();
outputStream=socket.getOutputStream();
objectOutputStream=new ObjectOutputStream(outputStream);
objectInputStream=new ObjectInputStream(inputStream);
}
public static void init() throws IOException {
pushServerSocket=new ServerSocket(8081);
System.out.println("-----------推送socket客户端初始化完毕-------------");
}
public static Socket getSocket() throws IOException {
return pushServerSocket.accept();
}
public void close(){
try {
if(objectInputStream!=null) {
objectInputStream.close();
}
if(inputStream!=null) {
inputStream.close();
}
if(objectOutputStream!=null) {
objectOutputStream.close();
}
if(outputStream!=null) {
outputStream.close();
}
System.out.println("------服务器IP:"+socket.getInetAddress()+"一次推送完成-------");
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}