关于Java Socket的编程例子总结

因为用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();
	}
}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值