socket通信例子_服务端写客户端读多线程写法

1、主程序

/**
* 主程序启动入口
*
* @param args
*/
public static void main(String[] args) {

ctx = new ClassPathXmlApplicationContext(APPLICATION_XML_FILE);
ctx.start();
//
SingletonMessagePush instance=SingletonMessagePush.getInstance();//单例服务类
try {
ServerSocket serverSocket=new ServerSocket(getMessagePushPort());//serverSocket,只负责监听客户端连接,一旦连接成功,服务端会新建一个socket负责与客户端通信
while(true){//不断监听客户端连接
Socket socket = serverSocket.accept();//返回一个客户端的Socket对象实例
//
System.out.println("【发现客户端连接>>>>>>】");
if(null!=socket){
CopyOnWriteArrayList<Socket> oldList=instance.getSocket();
for (Socket so : oldList) {
if(so.isConnected()==false||so.isClosed()==true){
instance.getSocket().remove(so);//移除
System.out.println(so.getInetAddress()+"从socket客户端集合移除。");
}
}
if(socket.isConnected()==true&&socket.isClosed()==false){
instance.getSocket().add(socket);//添加客户端socket
System.out.println("添加客户端:"+socket.getInetAddress()+",当前有效客户端总数:"+instance.getSocket().size());
}
}

}
} catch (Exception e) {
e.printStackTrace();
System.out.println("主程序启动时服务端socket异常");
}
}


2、推送消息单例类

package com.vxichina.cluster.persistence.core;

import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.Socket;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
* @author mingfeng.wang
* @date 2016年3月15日
* @time 上午10:54:18
* 向录屏程序推送消息的类
*/
public class SingletonMessagePush {
//有效客户端socket连接集合
private CopyOnWriteArrayList<Socket> socket=new CopyOnWriteArrayList<Socket>();
//线程池
private ExecutorService threadPool=Executors.newCachedThreadPool();
//private构造函数
private SingletonMessagePush(){

}
private static SingletonMessagePush instance;
//对外访问方法
public static SingletonMessagePush getInstance(){
if(null==instance){
instance=new SingletonMessagePush();
}
return instance;
}
/**
* 推送消息的主方法
* @param dataStr
*/
public void doMain(String dataStr){
try {
if(null!=dataStr&&!"".equals(dataStr)){
if(null!=socket&&socket.size()>0){
//#s 给所有有效连接的客户端推送消息
for (Socket sc : this.getSocket()) {
final String message=dataStr;
final Socket clientSocket=sc;
if(sc.isConnected()==true&&sc.isClosed()==false){
//new Thread(new Task(sc,dataStr)).start();//多线程
Thread.sleep(0);
//线程池方式
threadPool.execute(new Runnable() {
@Override
public void run() {
try {
System.out.println("当前线程name="+Thread.currentThread().getName()+", id="+Thread.currentThread().getId());
// 服务端写数据
Writer writer = new OutputStreamWriter(clientSocket.getOutputStream());
writer.write(message);
writer.flush();
System.out.println("成功给客户端"+clientSocket.getInetAddress()+"推送消息。消息内容:\n"+message);
//writer.close();//不能关闭,关闭会导致客户端close一段时间
}catch (Exception e) {
System.out.println("给客户端"+clientSocket.getInetAddress()+"推送消息异常。");
}
}
});
}
}
//#e
}else{
System.out.println("暂无客户端连接。");
}
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("doMain推送消息异常。");
}
}


public CopyOnWriteArrayList<Socket> getSocket() {
return socket;
}
public void setSocket(CopyOnWriteArrayList<Socket> socket) {
this.socket = socket;
}


}


3、模拟客户端访问

public class ClientSocketTest {

public static void main(String[] args) {
String host="192.68.19.64";//自定义
int port=9080;
try {
Socket client = new Socket(host, port);
while(true){
System.out.println("【>>>>>>客户端正在监听>>>>>>】,isConnected="+client.isConnected()+",isClosed="+client.isClosed());
// 客户端读数据
Reader reader = new InputStreamReader(client.getInputStream());
char chars[] = new char[64];
int len;
StringBuffer sb = new StringBuffer();
while ((len = reader.read(chars)) != -1) {
sb.append(new String(chars, 0, len));
}
System.out.println("客户端读数据结束。" );
reader.close();
//client.close();

}
}catch(java.net.SocketException e){
if(e.getMessage().equals("Connection reset")){
System.out.println("连接被重置,服务端已关闭。");
}
}catch (Exception e) {
e.printStackTrace();
System.out.println("客户端其它异常。");
}
}
}


===============================================================================
1、服务端监听端口
private static final String appConfigFile = "/app-config.properties";
public static void main(String[] args) {
SingletonServerSocket singletonServerSocket=SingletonServerSocket.getInstance();
try {
//System.out.println("端口:"+getMessagePushPort());
ServerSocket serverSocket=new ServerSocket(getMessagePushPort());
singletonServerSocket.setServerSocket(serverSocket);//serverSocket
while(true){
Socket socket = serverSocket.accept();//监听,接受客户端连接
if(null!=socket){
singletonServerSocket.setSocket(socket);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 从Properties文件中获取推送信息需要监听的socket通信端口
* @return
*/
public static int getMessagePushPort(){
int port=0;
Properties properties = new Properties();
try {
properties.load(Object.class.getResourceAsStream(appConfigFile));
} catch (IOException e) {
e.printStackTrace();
}
port=Integer.valueOf(properties.getProperty("messagePushPort").trim());
return port;
}


2、调用
SingletonServerSocket singletonServerSocket=SingletonServerSocket.getInstance();//单例类
//推送socket消息到客户端
singletonServerSocket.doMain(str.toString());


3、SingletonServerSocket 单例类-服务端写数据
public class SingletonServerSocket {
private ServerSocket serverSocket;
private Socket socket;
//private构造函数
private SingletonServerSocket(){

}
private static SingletonServerSocket instance;
//对外访问方法
public static SingletonServerSocket getInstance(){
if(null==instance){
instance=new SingletonServerSocket();
}
return instance;
}
/**
* 推送消息的主方法
* @param dataStr
*/
public void doMain(String dataStr){
try {
if(null!=dataStr&&!"".equals(dataStr)){
if(null!=socket){
new Thread(new Task(socket,dataStr)).start();//多线程
}else{
System.out.println("暂无客户端连接,无法完成写操作。");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 用来处理socket请求的多线程
*
*
*/
static class Task implements Runnable {

private Socket socket2;
private String data;

public Task(Socket socket, String data) {
this.socket2 = socket;
this.data = data;
}

public void run() {
try {
handleSocket();// 处理客户端socket
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 跟客户端Socket进行通信
*
*/
private void handleSocket(){
try {
// 服务端写数据
Writer writer = new OutputStreamWriter(socket2.getOutputStream());
writer.write(data);
System.out.println("服务端写数据:" + data);
writer.flush();
//writer.close();
} catch (java.net.SocketException e) {
System.out.println("无法找到写数据的客户端!");
} catch (Exception e) {
System.out.println("服务端写数据错误!");
}
// socket2.close();//服务端socket,不能关闭
}
}
public ServerSocket getServerSocket() {
return serverSocket;
}
public void setServerSocket(ServerSocket serverSocket) {
this.serverSocket = serverSocket;
}
public Socket getSocket() {
return socket;
}
public void setSocket(Socket socket) {
this.socket = socket;
}

}

4、客户端读数据
public class ClientSocket {

public static void main(String[] args) {
String host="192........";
int port=9099;
try {
Socket client = new Socket(host, port);
while(true){
System.out.println("client request...");

if(client.isClosed()){
client = new Socket(host, port);
}
// 客户端读数据
Reader reader = new InputStreamReader(client.getInputStream());
char chars[] = new char[64];
int len;
StringBuffer sb = new StringBuffer();
while ((len = reader.read(chars)) != -1) {
sb.append(new String(chars, 0, len));
}
System.out.println("客户端读数据:" + sb);
reader.close();
client.close();

}
} catch (Exception e) {
e.printStackTrace();
}
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值