java Socket 在客户端断开之后才可以接收到客户端发送的消息! 30C
    //客户端
 public class Test {
    private static boolean is = true;

    public static void main(String[] args) throws IOException,
            InterruptedException {

        Socket socket = new Socket("127.0.0.1", 6677);
        System.out.println("链接成功");
        Scanner scanner = new Scanner(System.in);
        while (is) {
            System.out.println("请输入!!!");
            int n = scanner.nextInt();
            switch (n) {
            case 1:
                OutputStream os = socket.getOutputStream();
                os.write("hello world".getBytes());
                os.flush();
                // os.close();
                // socket.close();
                // IoUtil.IoClose(os);
                System.out.println("发送成功");
                break;
            case 2:
                System.out.println("循环关闭");
                is = false;
                break;
            default:
                is = false;
                System.out.println("输入错误---循环关闭");
                break;
            }
        }
    }
}
 //服务器端  太多了 就贴一部分
 @Override
    public void run() {
        MessageThread messageThread = null;
        InputStream iss = null;
        InputStreamReader isr = null;
        BufferedReader br = null;
        while (is) {
            try {
                // 监听
                Socket socket = serverSocket.accept();
                System.out.println("链接成功");
                iss = socket.getInputStream();
                isr = new InputStreamReader(iss);
                br = new BufferedReader(isr);
                String len;
                StringBuffer sb = new StringBuffer();
                while ((len = br.readLine()) != null) {
                    sb.append(len);
                }
                System.out.println(sb.toString());
                // iss.close();
                // IoUtil.IoClose(br, isr, iss);
                SocketMap.put(sb.toString(), socket);
                /**
                 * 开启接受消息的线程
                 */
                messageThread = new MessageThread(socket);
                messageThread.start();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                messageThread.setFlag(false);
            }
        }

大致代码就这些 问题出在 socket 可以链接成功 但是 客户端发送的消息要等 客户端断开链接之后才能接收到 或者 关闭客户端的输出流也可以!
C#为客户端的时候也一样!

4个回答

readline()函数其实自带了一个阻塞,readline()读取的结束标识符是"\n",把客户端的os.write("hello world".getBytes()); 改成 os.write("hello world\n".getBytes()); 试试 服务器端同理

wei_armstrong
wei_armstrong 稳了,老哥
大约 2 个月之前 回复
wooshlele
可乐不对味 找了好久问题,还是你这个靠谱!
5 个月之前 回复
wjm1016
AMing* 问题解决了 你的方向是对的 解决有点问题 我已经解决 后面附上解决思路和链接
2 年多之前 回复
wjm1016
AMing* 我是题主,我的号不知道为什么被禁言了, 画个圈圈诅咒csdn。。。。。
2 年多之前 回复
ljq869115191
钢镚— 我刚才试了试 加了 /n 也试着换了一种输出的方式 read(char[],0,char[].length); 也不可以
2 年多之前 回复

没有具体看代码,感觉问题大概是流没有正确关闭吧。具体问题等大神解决吧,来观摩一下

qq_34550154
qq_34550154 回复仰望你的天空: 可能输出方式不对 阻塞了 我猜是这样的
2 年多之前 回复
ljq869115191
钢镚— 回复霸气男__: 对 但是问题出在 服务器可以发送给 客户端 测试过没问题! 客户端给不了服务器 !
2 年多之前 回复
xzsrbr163
霸气男__ 回复仰望你的天空: 你是要保持实时通信,获取服务端的返回信息吗?
2 年多之前 回复
ljq869115191
钢镚— 你感觉的是哪里! 我再琢磨琢磨!
2 年多之前 回复

同样的问题等大神解决

我再顶顶! c币 不够我再加!

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
其他相关推荐
Android socket通讯客户端连不上服务器问题,以及发送消息程序就闪退
原本以为是线程问题但是好像又不是,实在找不到怎么弄了 这是客户端: package com.chiaki.mysocketobject; import android.content.Intent; import android.os.Handler; import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.EditText; import android.widget.ImageButton; import android.widget.ListView; import android.widget.TextView; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.Socket; import java.util.ArrayList; import java.util.List; public class ChatActivity extends AppCompatActivity implements Runnable{ private static final String HOST = "172.16.2.54"; private static final int PORT = 12345; private MsgAdapter adapter; private ListView msgListView; private List<Msg> msgList=new ArrayList<Msg>(); private ImageButton send; private ImageButton connect; private EditText edit; private TextView ctext; private Socket socket; private BufferedReader in = null; private PrintWriter out = null; private String content = ""; private StringBuilder sb = null; public Handler handler = new Handler() { public void handleMessage(Message msg) { if (msg.what == 0x123) { sb.append(content); ctext.setText(sb.toString()); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_chat); adapter=new MsgAdapter(ChatActivity.this,R.layout.chat_list_view,msgList); ImageButton back = (ImageButton)findViewById(R.id.back); ImageButton voiceButton = (ImageButton)findViewById(R.id.voiceButton); connect = (ImageButton)findViewById(R.id.connectButton); send = (ImageButton)findViewById(R.id.send); edit = (EditText)findViewById(R.id.edit); ctext = (TextView)findViewById(R.id.chattext); msgListView=(ListView)findViewById(R.id.msg_list_view); sb = new StringBuilder(); msgListView.setAdapter(adapter); // 点击按钮实例化Socket对象,与服务端进行连接,获取输入输出流 // 连接服务器,要在子线程中 connect.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new Thread() { @Override public void run() { super.run(); try { // 创建socket,连接服务器 socket = new Socket(HOST, PORT);//连接服务器 in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));//接收消息的流对象 out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);//发送消息的流对象 } catch (Exception e) { e.printStackTrace(); } } }.start(); } }); back.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(ChatActivity.this,SocketActivity.class); startActivity(intent); } }); send.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String con=edit.getText().toString(); edit.setText(""); if (socket.isConnected()) { if (!socket.isOutputShutdown()) { out.println(con);//点击按钮发送消息 } } } }); //启动线程,连接服务器,并用死循环守候,接收服务器发送过来的数据 new Thread(ChatActivity.this).start(); } // 重写run方法,在该方法中输入流的读取 public void run() { try { while (true) { //死循环守护,监控服务器发来的消息 if (socket.isConnected()) { //如果服务器没有关闭 if (!socket.isInputShutdown()) { //连接正常 if ((content = in.readLine()) != null) { //如果输入流没有断开 content += "\n"; //读取接收的信息 handler.sendEmptyMessage(0x123); //会发送一个空消息,但是指定了Message的what属性 } } } } } catch (Exception e) { e.printStackTrace(); } } } 这是layout文件主要的控件: <ImageButton //建立连接按钮 android:layout_width="wrap_content" android:layout_height="wrap_content" app:srcCompat="@android:drawable/checkbox_on_background" android:id="@+id/connectButton" android:layout_alignParentStart="true" android:layout_below="@+id/edit" /> <TextView //显示消息 android:text="TextView" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/chattext" /> <ImageButton //编辑消息 android:layout_width="wrap_content" android:layout_height="wrap_content" app:srcCompat="@android:drawable/ic_btn_speak_now" android:id="@+id/voiceButton" android:layout_below="@+id/edit" android:layout_centerHorizontal="true" /> <ImageButton //发送消息 android:layout_width="wrap_content" android:layout_height="40dp" app:srcCompat="@android:drawable/ic_menu_send" android:id="@+id/send" android:backgroundTint="?attr/colorButtonNormal" android:layout_alignParentBottom="true" android:layout_alignParentEnd="true" /> 这是服务端: import java.io.DataInputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; public class Server { // 定义相关的参数,端口,存储Socket连接的集合,ServerSocket对象 // 以及线程池 private static final int PORT = 12345; private List<Socket> mList = new ArrayList<Socket>(); private ServerSocket server = null; private ExecutorService myExecutorService = null; public static void main(String[] args) { new Server(); } public Server() { try { server = new ServerSocket(PORT); // 创建线程池 myExecutorService = Executors.newCachedThreadPool(); System.out.println("服务端运行中...\n"); Socket client = null; while (true) { client = server.accept(); mList.add(client); myExecutorService.execute(new Service(client)); } } catch (Exception e) { e.printStackTrace(); } } class Service implements Runnable { private Socket socket; private BufferedReader in = null; private String msg = ""; public Service(Socket socket) { this.socket = socket; try { in = new BufferedReader(new InputStreamReader(socket.getInputStream())); System.out.println("用户:" + this.socket.getInetAddress() + "~加入了聊天室" + "当前在线人数:" + mList.size()); } catch (IOException e) { e.printStackTrace(); } } @Override public void run() { try { while (true) { if ((msg = in.readLine()) != null) { if (msg.equals("bye")) { System.out.println("~~~~~~~~~~~~~"); mList.remove(socket); in.close(); System.out.println("用户:" + socket.getInetAddress() + "退出:" + "当前在线人数:" + mList.size()); socket.close(); break; } else { System.out.println(socket.getInetAddress() + " 说: " + msg); this.sendmsg(); } } } } catch (Exception e) { e.printStackTrace(); } } // 为连接上服务端的每个客户端发送信息 public void sendmsg() { int num = mList.size(); for (int index = 0; index < num; index++) { Socket mSocket = mList.get(index); PrintWriter pout = null; try { pout = new PrintWriter( new BufferedWriter(new OutputStreamWriter(mSocket.getOutputStream(), "UTF-8")), true); pout.println(msg); } catch (IOException e) { e.printStackTrace(); } } } } }
通过C++/java socket向服务器端传递字符串并接收服务器的反馈字符串与使用浏览器实现相同功能有何区别?
1.在写一个打开网络服务的软件的接口时(win10环境),用c++和java 的socket分别写了两个客户端,客户端的功能是通过端口8081向本地服务器localhost发送字符串“?scanX”,然后接收服务器的反馈“done!",但是在接收的过程中会出现网络中断,要写接口的软件报错;但如果用浏览器,直接在地址栏输入"http://127.0.0.1:8081/?scanB" ,浏览器会直接显示"done!".我想解决的是用c++写一个接口exe能及时向服务器传递字符串并接收反馈,但此时反馈出现了问题,本人小白,问了很多前辈也未能解决疑问,在此求教各位前辈,大佬。 2.以下为c++代码段,运行到"sended request success!"后网络服务器不知为何断开,要写接口的软件报错 #include <iostream> #include <windows.h> using namespace std; //在windows网络编程中需要引入库 #pragma comment(lib, "wsock32.lib") int main(int argc, char *argv[]) { //在windows网络编程中导入库,linux中不需要 WSADATA Ws; if (WSAStartup(MAKEWORD(2, 2), &Ws) != 0) { cout << "Init Windows Socket Failed::" << GetLastError() << endl; return -1; } //通过域名获取IP地址 HOSTENT *host_entry = gethostbyname("127.0.0.1"); if (!host_entry){ return -1; } //将网络字节序的网络地址转为本地字节序 char *serverIP = inet_ntoa(*((struct in_addr *)host_entry->h_addr)); cout << "server IP is " << serverIP << endl; //创建socket并且绑定了TCP协议 int hsocket = socket(AF_INET, SOCK_STREAM, 0); //socket创建失败,一般都是系统资源没有了,或者没有权限 if (hsocket == INVALID_SOCKET) *** { cout << "Create Socket Failed::" << GetLastError() << endl; return -2; } //连接http服务器 sockaddr_in servAddr; servAddr.sin_family = AF_INET; servAddr.sin_port = htons(8081); //指定端口号 servAddr.sin_addr.S_un.S_addr = inet_addr(serverIP); if (connect(hsocket, (struct sockaddr*)&servAddr, sizeof(servAddr)) == -1) { cout << "Connect error" << endl; return -3; } else cout << "Connected "<<serverIP<<" successed!" << endl; //发出页面URL请求数据 char req[] = "?connect0"; //注意send并不能保证你指定大小的数据它能够全部发送, if (send(hsocket, req, (int)strlen(req), 0) < 0) { cout << "send request error" << endl; return -4; } cout << "sended request success!" << endl; //接收数据的缓冲,应为是字符串所以结尾要加\0,我们一开始就将它全部置0 char buffer[10000] = {0}; int len; if ( recv(hsocket, buffer, sizeof(buffer)-1, 0) <0) { cout << "read error" << endl; exit(1); } cout << buffer << endl; getchar(); return 0; } ``` ``` 这是运行结果 ![图片说明](https://img-ask.csdn.net/upload/201903/24/1553395763_716349.png) 软件报错(查百度说这句话是因为读取软件数据导致的,不知正确与否) ![图片说明](https://img-ask.csdn.net/upload/201903/24/1553395434_777007.png) 对比使用浏览器通信,能直接收到反馈 ![图片说明](https://img-ask.csdn.net/upload/201903/24/1553395626_39803.png)
java socket server
用java编写的一个socket服务端,通过一个tcp测试工具测试这个服务端,发现发送数据给服务端,服务端接收不到,当tcp测试工具断开连接后,测试工具发送的字符串才被服务端接收到,这是为什么? java socket服务端代码 [code="java"] package com.myserver.server; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class MultiThreadServer { private int port = 6666; private ServerSocket serverSocket; private ExecutorService executorService;//线程池 private final int POOL_SIZE = 10;//单个CPU线程池大小 public MultiThreadServer() throws IOException { serverSocket = new ServerSocket(port); //Runtime的availableProcessor()方法返回当前系统的CPU数目. executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * POOL_SIZE); System.out.println("server start"); } public void service() { while (true) { Socket socket = null; try { //接收客户连接,只要客户进行了连接,就会触发accept();从而建立连接 socket = serverSocket.accept(); executorService.execute(new Handler(socket)); Count.add(); System.out.println("client number " + Count.num); } catch (Exception e) { e.printStackTrace(); } } } public static void main(String[] args) throws IOException { new MultiThreadServer().service(); } } class Handler implements Runnable { private Socket socket; public Handler(Socket socket) { this.socket = socket; } public void run() { try { System.out.println("a client connect " + socket.getInetAddress() + ":" + socket.getPort()); PrintWriter writer = new PrintWriter(socket.getOutputStream()); writer.println("connect success"); writer.flush(); BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); String readLine = reader.readLine(); while (true) { if (readLine != null) { System.out.println(readLine); readLine = reader.readLine(); } else { break; } } writer.close(); reader.close(); } catch (IOException e) { System.out.println("a client leave"); Count.sub(); System.out.println("client number " + Count.num); } finally { try { if (socket != null) { socket.close(); } } catch (IOException e) { e.printStackTrace(); } } } } class Count { public static int num = 0; public static void add() { num += 1; } public static void sub() { num -= 1; } } [/code] java服务端状态输出如下 server start client number 1 a client connect /127.0.0.1:50437 affff tcp测试工具截图 [img]http://dl.iteye.com/upload/attachment/526919/4726dc79-31b2-3216-8887-de70efdd80cb.jpg[/img] 补充说明: tcp测试工具能够正常连接到服务端,但是文本数据发送,服务端不会实时显示,只有当测试工具断开连接时,这时,服务端才显示刚才测试工具发送的文本数据
java定时器超时后关闭socket出现socket closed 异常的问题
package my.start; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.Timer; import java.util.TimerTask; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; //创建AutoStart类,让他实现ServletContextListener(服务程序上下文监听器)接口 //实现ServletContextListener接口需要重写contextDestroyed()和contextInitialized()两个方法 //记得要在web.xml文件中加入 // <listener> // <listener-class>my.test.AutoStart</listener-class> // </listener> //这样,tomcat在启动时,就会同时调用该接口的contextInitialized()方法 //在contextInitialized()方法中,开启一个线程,用soket监听一个端口,从而实现TCP通信 public class AutoStart extends HttpServlet{ private static final long serialVersionUID = 1L; private int soketPort = 9014;//要监听的服务器端口,可以根据需要进行修改 @Override public void init() throws ServletException { // TODO Auto-generated method stub super.init(); new MyThread().start();//创建一个MyThread线程对象,并启动线程 System.out.println("开启监听线程"); } //创建MyThread类,继承Thread方法 class MyThread extends Thread { //重写Thread类的run()方法,用来实现MyThread线程的功能 public void run() { //System.out.println("测试开始"); try { ServerSocket ss = new ServerSocket(soketPort); System.out.println("监听到"+(soketPort+"")+"端口"); while(true){ //System.out.println("已经创建soket"); //ss对象的accept()方法可以监听指定端口有没有TCP连接 //在没有TCP连接之前程序将阻塞在这里 Socket socket = ss.accept(); System.out.println("有客户端接入"); //监听到指定端口有TCP连接后,创建soket对象,程序不再堵塞,往下执行 //创建一个线程,去监听客户端通过TCP发来的数据 Thread sockThread=new SocketTherad(socket); //启动线程 sockThread.start(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } int timeNum; class SocketTherad extends Thread{ //继承Thread类来创建线程 Socket socket; InputStream is; OutputStream os; boolean run_flag=true;//控制run()函数是否继续运行标志位 Timer heartBeatTimer = new Timer(); //心跳包定时器 private void startHeartBeatThread() { TimerTask heartBeatTask = new TimerTask() { public void run() { timeNum++; System.out.println("timerNum="+(timeNum+"")); if(timeNum==2){//超时则关闭socket连接及定时器 try { is.close(); os.close();//关闭输出流 socket.close();//关闭soket run_flag=false;//跳出死循环 System.out.println("TCP连接断开"); heartBeatTimer.cancel();//关闭定时器 } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }; heartBeatTimer.schedule(heartBeatTask, 10*1000, 10*1000); } public SocketTherad(Socket socket) { this.socket = socket;//传递过来的soket参数赋予给socket对象 } public void run() {//run()函数用来实现线程要完成的任务 startHeartBeatThread(); while(run_flag) { try { String str = null; is = socket.getInputStream();//获取输入流 os=socket.getOutputStream(); byte[] buffer = new byte[200];//数据缓冲区; int length=0; length = is.read(buffer);//读取接收到的数据流长度 if(length != (-1)){//不是-1,说明读取到有效的数据 str = new String(buffer,0,length);//输入流转换成str字符串 System.out.print("收到数据:"); System.out.println(str); } else if(length == (-1)){//接收到数据长度为-1,说明客户端主动关闭了TCP连接 is.close();//关闭输入流 os.close();//关闭输出流 socket.close();//关闭soket run_flag=false;//跳出死循环 System.out.println("TCP连接断开"); } buffer = null; System.gc();//垃圾回收 } catch (IOException e) { e.printStackTrace(); } } } } } ``` ```
Java的客户端与服务器,客户端可以发信息,想加一个让服务器也能发信息?
```客户端代码: package Other; import java.awt.Container; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedReader; import java.io.IOException; import java.io.PrintWriter; import java.io.Writer; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketAddress; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTextArea; import javax.swing.JTextField; public class Server extends JFrame { private JPanel p1, p2, p4, p5, p6; private JLabel lb1, lb2, lb3, lb4; private Container container; private JTextField t1, t2; private static JTextArea ta; private JButton bt; public Server() { this.setTitle("服务器"); container = this.getContentPane(); container.setLayout(new FlowLayout(FlowLayout.LEFT)); lb1 = new JLabel("服务器启动面板"); lb2 = new JLabel("服务器主机名:"); lb3 = new JLabel("服务器端口:"); lb4 = new JLabel("服务器收到客户机消息面板"); bt = new JButton("启动服务器"); bt.addActionListener(new btActionListener()); t1 = new JTextField(10); t2 = new JTextField(5); ta = new JTextArea(15, 40); // ta.addActionListener(new taActionListener()); p1 = new JPanel(); p2 = new JPanel(); p4 = new JPanel(); p5 = new JPanel(); p6 = new JPanel(); p1.add(lb1); container.add(p1); p2.add(lb2); p2.add(t1); p2.add(lb3); p2.add(t2); p2.add(bt); container.add(p2); p4.add(lb4); container.add(p4); p5.add(ta); p6.add(p5); container.add(p6); this.setSize(500, 500); this.setVisible(true); this.setResizable(false); } private ServerSocket listenSocket =null; private Socket toClientSocket = null; private BufferedReader in; private PrintWriter out; public static int clientCounts = 0; public class taActionListener implements ActionListener{ @Override public void actionPerformed(ActionEvent e) { } } public class btActionListener implements ActionListener { public void actionPerformed(ActionEvent arg0) { try { bt.setEnabled(false); String hostName = t1.getText(); int hostPort = Integer.parseInt(t2.getText()); SocketAddress serverAddr = new InetSocketAddress( InetAddress.getByName(hostName),hostPort); listenSocket = new ServerSocket(); listenSocket.bind(serverAddr); ta.append("服务器开始等待客户机连接…\n"); } catch (Exception e) {} //创建匿名线程,创建响应客户机的会话线程 new Thread(new Runnable() { @Override public void run() { try { while (true) { // 处理客户机连接 toClientSocket = listenSocket.accept(); // 侦听并接受客户机连接 clientCounts++; ta.append(toClientSocket.getRemoteSocketAddress() + "客户机编号" + clientCounts + "会话开始…\n"); // 创建客户线程clientThread,实现一客户一线程 Thread clientThread = new ClientThread(toClientSocket, clientCounts); clientThread.start(); }//end while } catch (IOException e) { JOptionPane.showMessageDialog(null, e.getMessage(), "错误提示", JOptionPane.ERROR_MESSAGE); return; } }//end run() }).start(); } } private void formWindowClosing (java.awt.event.WindowEvent evt){ try { if(in != null)in.close(); if(out != null)out.close(); if (listenSocket != null)listenSocket.close(); if (toClientSocket != null)toClientSocket.close(); } catch (Exception e) {} } public static void main(String[] args) { new Server(); } public static JTextArea getScreen() { return ta; } } 服务器代码: package Other; import java.awt.Container; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketAddress; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTextArea; import javax.swing.JTextField; public class Client extends JFrame { private JPanel p1, p2, p3, p5, p6, p7; private JLabel lb1, lb2, lb3, lb4, lb5; private Container container; private JTextField t1, t2, t3; private static JTextArea ta; private JButton bt1, bt2; public Client(){ this.setTitle("客户机"); container = this.getContentPane(); container.setLayout(new FlowLayout(FlowLayout.LEFT)); lb1 = new JLabel("通信面板"); lb2 = new JLabel("服务器主机名:"); lb3 = new JLabel("服务器端口:"); lb4 = new JLabel("待发送消息:"); lb5 = new JLabel("服务器Echo消息面板"); bt1 = new JButton("连接服务器"); bt2 = new JButton(" 发 言 "); bt1.addActionListener(new bt1ActionListener()); bt2.addActionListener(new bt2ActionListener()); t1 = new JTextField(10); t2 = new JTextField(5); t3 = new JTextField(25); ta = new JTextArea(15, 40); p1 = new JPanel(); p2 = new JPanel(); p3 = new JPanel(); p5 = new JPanel(); p6 = new JPanel(); p7 = new JPanel(); p1.add(lb1); container.add(p1); p2.add(lb2); p2.add(t1); p2.add(lb3); p2.add(t2); p2.add(bt1); container.add(p2); p3.add(lb4); p3.add(t3); p3.add(bt2); container.add(p3); p5.add(lb5); container.add(p5); p6.add(ta); p7.add(p6); container.add(p7); this.setSize(500, 500); this.setVisible(true); this.setResizable(false); } private Socket clientSocket = null; private BufferedReader in; private PrintWriter out; public class bt1ActionListener implements ActionListener { public void actionPerformed(ActionEvent arg0) { try { bt1.setEnabled(false); String remoteName = t1.getText(); int remotePort = Integer.parseInt(t2.getText()); SocketAddress remoteAddr = new InetSocketAddress( InetAddress.getByName(remoteName),remotePort); clientSocket = new Socket(); clientSocket.connect(remoteAddr); ta.append("连接服务器成功,会话开始…\n"); out = new PrintWriter(new OutputStreamWriter( clientSocket.getOutputStream(),"UTF-8"),true); in = new BufferedReader(new InputStreamReader( clientSocket.getInputStream(),"UTF-8")); } catch (Exception e) { JOptionPane.showConfirmDialog(null, e.getMessage(), "连接错误",JOptionPane.ERROR_MESSAGE); return; } } } public class bt2ActionListener implements ActionListener { public void actionPerformed(ActionEvent arg0) { if(clientSocket == null){ JOptionPane.showMessageDialog(null, "请先检查服务器连接情况。\n确保客户及连接服务器!", "错误提示", JOptionPane.ERROR_MESSAGE); return; } String outStr = t3.getText(); if(outStr.length() == 0){ JOptionPane.showMessageDialog(null, "请输入发送消息!", "提示", JOptionPane.ERROR_MESSAGE); return; } out.println(outStr); t3.setText(""); try { String inStr; inStr = in.readLine(); ta.append("Echo:" + inStr + "\n"); } catch (Exception e) { JOptionPane.showMessageDialog(null, "客户机接收消息错误!", "错误提示", JOptionPane.ERROR_MESSAGE); return; } } } private void formWindowClosing(java.awt.event.WindowEvent evt){ try { if(in != null)in.close(); if(out != null)out.close(); if(clientSocket != null)clientSocket.close(); } catch (Exception e) {} } public static void main(String[] args) { new Client(); } } 多线程: package Other; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.Socket; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; public class ClientThread extends Thread { private Socket toClientSocket = null; private BufferedReader in; private PrintWriter out; public static int clientCounts = 0; public ClientThread(Socket toClientSocket,int clientCounts){ this.toClientSocket = toClientSocket; this.clientCounts = clientCounts; } @Override public void run() { try { in = new BufferedReader( new InputStreamReader(toClientSocket.getInputStream(),"UTF-8")); out = new PrintWriter( new OutputStreamWriter(toClientSocket.getOutputStream(),"UTF-8"),true); //根据服务器协议,在网络流上进行读写操作 String recvStr; while((recvStr = in.readLine()) != null){ //客户机关闭,反复等待 System.out.println(recvStr); Date date = new Date(); //和接受客户机消息 DateFormat format = new SimpleDateFormat("yyyy-mm-dd hh:mm:ss"); String time = format.format(date); //解析并显示收到的信息 Server.getScreen().append(toClientSocket.getRemoteSocketAddress() + "客户机编号:" + clientCounts + "消息:" + recvStr + ":" + time + "\n"); //按照Echo协议原封不动会送消息 out.println(toClientSocket.getLocalAddress() + "客户机编号:" + clientCounts + "Echo消息:" + recvStr + ":" + time); }//end while Server.clientCounts--; //远程客户机断开,释放资源 if(in != null)in.close(); if(out != null)out.close(); if (toClientSocket != null)toClientSocket.close(); } catch (Exception e) {} }//end run }//end class
大师帮忙实现客户端的一对一会话,谢了。
import java.net.InetSocketAddress; import java.nio.charset.Charset; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.textline.LineDelimiter; import org.apache.mina.filter.codec.textline.TextLineCodecFactory; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** *服务端 */ public class MinaServer { protected static Logger logger = LoggerFactory.getLogger(MinaServer.class); static int PORT=7082; static IoAcceptor acceptor=null; public static void main(String[] args){ try{ acceptor=new NioSocketAcceptor(); //设置编码过滤器 acceptor.getFilterChain().addLast("codec",new ProtocolCodecFilter( new TextLineCodecFactory(Charset.forName("UTF-8"), LineDelimiter.WINDOWS.getValue(), LineDelimiter.WINDOWS.getValue()))); //设置缓冲区的大小 acceptor.getSessionConfig().setReadBufferSize(1024); acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 90); acceptor.setHandler(new Myhandler()); acceptor.bind(new InetSocketAddress(PORT)); logger.info("服务端启动成功... 端口号为:" + PORT); }catch(Exception e){ logger.error("服务端启动异常....", e); e.printStackTrace(); } } } import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** *服务端处理器: * */ public class Myhandler extends IoHandlerAdapter{ protected static Logger logger = LoggerFactory.getLogger(Myhandler.class); // 发送消息异常时触发 @Override public void exceptionCaught(IoSession session, Throwable cause) throws Exception { logger.error("服务端发送消息异常"+cause); } // 接收到消息时触发 @Override public void messageReceived(IoSession session, Object message) throws Exception { //获取客户端发过来的key String key = message.toString(); logger.info("message :"+message.toString()); String carPark_id = key.substring(key.indexOf("=") + 1); logger.info("carPark_id :"+carPark_id); //保存客户端的会话session SessionMap sessionMap = SessionMap.newInstance(); sessionMap.addSession(carPark_id, session); sessionMap.getSession(key); // String msg=(String) message; // logger.info("服务端接收到数据"+msg); // if("exit".equals(msg)){ // session.close(true); // } // Date date=new Date(); // SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd"); // session.write(sdf.format(date)); // //拿到所有的客户端Session // Collection<IoSession> sessions = session.getService().getManagedSessions().values(); // for (IoSession sess : sessions) { // sess.write("所有客户端收到消息"); // } } // 发送消息成功后触发 @Override public void messageSent(IoSession session, Object message) throws Exception { logger.info("服务端发送信息成功!"); } // 会话关闭时触发 @Override public void sessionClosed(IoSession session) throws Exception { logger.debug("客户端与服务端断开连接!"); } // 创建会话时触发 @Override public void sessionCreated(IoSession session) throws Exception { logger.info("sessionCreated"); } // 会话空闲时触发 // 当连接空闲时被触发。使用IoSessionConfig中的setIdleTime(IdleStatus status, int // idleTime)方法可以设置session的空闲时间。如果该Session的空闲时间超过设置的值,该方法被触发,可以通过session.getIdleCount(status)来获取sessionIdle被触发的次数。 @Override public void sessionIdle(IoSession session, IdleStatus status) throws Exception { logger.info("服务端进入空闲状态..."); } // 打开会话时触发 // 会话创建之后--》会话打开 @Override public void sessionOpened(IoSession session) throws Exception { logger.info("服务端与客户端已连接sessionOpened"); } } import java.net.InetSocketAddress; import java.nio.charset.Charset; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.service.IoConnector; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.textline.LineDelimiter; import org.apache.mina.filter.codec.textline.TextLineCodecFactory; import org.apache.mina.transport.socket.nio.NioSocketConnector; /** * 客户端 */ public class MinaClient { private static String host="127.0.0.1"; private static int port=7082; public static void main(String[] args) { // TODO Auto-generated method stub IoSession session=null; // 创建一个非阻塞的客户端程序 IoConnector connector=new NioSocketConnector(); // 设置链接超时时间 connector.setConnectTimeoutMillis(3000*10); //设置过滤器 connector.getFilterChain().addLast("coderc", new ProtocolCodecFilter( new TextLineCodecFactory(Charset.forName("UTF-8"), LineDelimiter.WINDOWS.getValue(), LineDelimiter.WINDOWS.getValue()))); connector.setHandler(new MyClientHandler()); //连接到服务端 ConnectFuture future=connector.connect(new InetSocketAddress(host,port)); future.awaitUninterruptibly(); //等待我们的连接 session=future.getSession(); session.write("你好!服务大哥"); session.getCloseFuture().awaitUninterruptibly(); //等待关闭链接 connector.dispose(); } } import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.session.IoSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class MyClientHandler extends IoHandlerAdapter { protected static Logger logger = LoggerFactory.getLogger(MyClientHandler.class); // 发送消息异常时触发 @Override public void exceptionCaught(IoSession session, Throwable cause) throws Exception { logger.debug("客户端发送消息异常exceptionCaught"); } // 接收到消息时触发 @Override public void messageReceived(IoSession session, Object message) throws Exception { // String msg=(String) message; // logger.info("客户端收到数据:"+msg); logger.info("-----服务端返回的json数据----"); String s = message.toString(); logger.info("客户端收到消息: :" + s); logger.info("消息长度为:" + s.length()); } @Override public void sessionIdle(IoSession session, IdleStatus status) throws Exception { // TODO 自动生成的方法存根 logger.info("-客户端与服务端连接[空闲] - " + status.toString()); if(session != null){ session.close(true); } } } import java.util.HashMap; import java.util.Map; import org.apache.mina.core.session.IoSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @Description: 单例工具类,保存所有mina客户端连接 * @author whl * @date 2014-9-29 上午10:09:15 * */ public class SessionMap { private final static Logger LOGGER=LoggerFactory.getLogger(SessionMap.class); private static SessionMap sessionMap = null; private Map<String, IoSession>map = new HashMap<String, IoSession>(); //构造私有化 单例 private SessionMap(){} /** * @Description: 获取唯一实例 * @author whl * @date 2014-9-29 下午1:29:33 */ public static SessionMap newInstance(){ LOGGER.debug("SessionMap单例获取---"); if(sessionMap == null){ sessionMap = new SessionMap(); } return sessionMap; } /** * @Description: 保存session会话 * @author whl * @date 2014-9-29 下午1:31:05 */ public void addSession(String key, IoSession session){ LOGGER.debug("保存会话到SessionMap单例---key=" + key); this.map.put(key, session); } /** * @Description: 根据key查找缓存的session * @author whl * @date 2014-9-29 下午1:31:55 */ public IoSession getSession(String key){ LOGGER.debug("获取会话从SessionMap单例---key=" + key); return this.map.get(key); } /** * @Description: 发送消息到客户端 * @author whl * @date 2014-9-29 下午1:57:51 */ public void sendMessage(String[] keys, Object message){ for(String key : keys){ IoSession session = getSession(key); LOGGER.debug("反向发送消息到客户端Session---key=" + key + "----------消息=" + message); if(session == null){ return; } session.write(message); } } }
vue前端websocket连接不上springboot,报错Connection closed before receiving a handshake response
搞定了,我的代码写的基本没有问题,毕竟都是按着教程一步一步来的,主要问题在于,我的开发环境和教程不一致,我是前后端分离,请求8080即请求的前端项目,当然会超时然后建立连接失败。我查看了一下前后端各自的端口:前端8080,后端63000,然后把 ``` this.sock = new WebSocket("ws:localhost:8080/websocket");//建立连接 ``` 改成 ``` this.sock = new WebSocket("ws:localhost:63000/websocket");//建立连接 ``` 就可以了,换成后端的端口号。 --- 以下是原问题 --- 照着网上的教程写的例子,整合到自己的项目中。前端用vue写的,js里几乎和教程一模一样,主要问题在于 ``` this.sock = new WebSocket("ws:localhost:8080/websocket");//建立连接 ``` --- **创建的websocket内的方法都是null,如图:** ![图片说明](https://img-ask.csdn.net/upload/201909/24/1569293600_266157.png) --- **然后观察控制台内过了一段时间报错,提示:** ``` WebSocket connection to 'ws://localhost:8080/websocket' failed: Connection closed before receiving a handshake response ``` --- **控制台错误详情见图:** ![图片说明](https://img-ask.csdn.net/upload/201909/24/1569294057_247788.png) --- **前端代码:** ``` webSocket() { debugger; // 建立socket连接 if ('WebSocket' in window) {//判断当前浏览器是否支持webSocket // this.sock = new WebSocket("ws:localhost:8080/bootTest/websocket");//建立连接(带后端项目名) this.sock = new WebSocket("ws:localhost:8080/websocket");//建立连接(不带后端项目名) } else { alert('你的浏览器暂不支持websocket :('); } var sock = this.sock; console.log(sock); sock.onopen = function (e) {//成功建立连接 console.log(e); }; sock.onmessage = function (e) {//接收到消息 console.log(e) $(".message").append("<p><font color='red'>"+e.data+"</font>") }; sock.onerror = function (e) {//连接发生错误 console.log(e); }; sock.onclose = function (e) {//连接关闭 console.log(e); }; ////监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。 window.onbeforeunload = function(){ websocket.close(); }; } ``` --- --- --- --- 后端代码: ``` import java.io.IOException; import java.util.concurrent.CopyOnWriteArraySet; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import javax.websocket.*; import lombok.extern.slf4j.Slf4j; @Slf4j @ServerEndpoint("/websocket") public class WebSocketServer { //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。 private static int onlineCount = 0; //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。 private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>(); //与某个客户端的连接会话,需要通过它来给客户端发送数据 private Session session; /** * 连接建立成功调用的方法*/ @OnOpen public void onOpen(Session session) { this.session = session; webSocketSet.add(this); //加入set中 addOnlineCount(); //在线数加1 log.info("有新连接加入!当前在线人数为" + getOnlineCount()); try { sendMessage("连接成功"); } catch (IOException e) { log.error("websocket IO异常"); } } // //连接打开时执行 // @OnOpen // public void onOpen(@PathParam("user") String user, Session session) { // currentUser = user; // System.out.println("Connected ... " + session.getId()); // } /** * 连接关闭调用的方法 */ @OnClose public void onClose() { webSocketSet.remove(this); //从set中删除 subOnlineCount(); //在线数减1 log.info("有一连接关闭!当前在线人数为" + getOnlineCount()); } /** * 收到客户端消息后调用的方法 * @param message 客户端发送过来的消息 */ @OnMessage public void onMessage(String message, Session session) { log.info("来自客户端的消息:" + message); //群发消息 for (WebSocketServer item : webSocketSet) { try { item.sendMessage(message); } catch (IOException e) { e.printStackTrace(); } } } /** * 发生错误 * @param session * @param error */ @OnError public void onError(Session session, Throwable error) { log.error("发生错误"); error.printStackTrace(); } public void sendMessage(String message) throws IOException { this.session.getBasicRemote().sendText(message); } /** * 群发自定义消息 * */ public static void sendInfo(String message) throws IOException { log.info(message); for (WebSocketServer item : webSocketSet) { try { item.sendMessage(message); } catch (IOException e) { continue; } } } public static synchronized int getOnlineCount() { return onlineCount; } public static synchronized void addOnlineCount() { WebSocketServer.onlineCount++; } public static synchronized void subOnlineCount() { WebSocketServer.onlineCount--; } } ```
关于WebSocket的问题 为什么浏览器关闭后会出一下异常
错误信息 ```java.net.SocketException: Software caused connection abort: recv failed at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.read(SocketInputStream.java:129) at java.net.SocketInputStream.read(SocketInputStream.java:90) at test.UserSocket.run(UserSocket.java:43) java.net.SocketException: Software caused connection abort: recv failed at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.read(SocketInputStream.java:129) at java.net.SocketInputStream.read(SocketInputStream.java:90) at test.UserSocket.run(UserSocket.java:43) ``` 这是一个WebScoket 的小测试。我开了3个浏览器测试正常后,关闭其中一个就会这个异常以下是我的代码麻烦各位大神给看看 ``` package test; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import java.util.List; import sun.applet.Main; public class ServerSocketTest { public static List<Socket> clientSocket = new ArrayList<Socket>(); public ServerSocketTest() throws IOException{ ServerSocket ss = new ServerSocket(30000); System.out.println("服务器启动等待客户端连接"); while(true){ Socket s =ss.accept();//等待客户端连接 clientSocket.add(s); System.out.println("客户端总人数"+clientSocket.size()); //为新用户启动线程 new UserSocket(s).start(); } } public static void main(String[] args) throws IOException { new ServerSocketTest(); } } ``` 下面是线程代码 ``` package test; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.net.SocketException; import java.security.MessageDigest; import java.util.Iterator; import java.util.regex.Matcher; import java.util.regex.Pattern; import sun.misc.BASE64Encoder; public class UserSocket extends Thread{ private Socket socket; public UserSocket(Socket socke){ this.socket = socke; } @Override public void run() { try { InputStream is = socket.getInputStream();//获取用户输入流 OutputStream ops = socket.getOutputStream();//获取用户输出流 byte[] buff = new byte[1024];//字节 String red = ""; //用了存放客户端请求过来的内容(客户端信息) // 读取数据,此时建立与wabSocket的握手 int count = is.read(buff);//读取客户端请求内容的长度 if(count > 0){ //客户端请求数据转化字符串 red = new String(buff,0,count); //获取WebSocket的值 String seckey = getSecWebSocketKey(red); String response = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: " + "websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: " + getSecWebSocketAccept(seckey) + "\r\n\r\n"; //推送向客户端 ops.write(response.getBytes("utf-8")); int hasRedad = 0; // 不断读取WebSocket发送过来的数据 System.out.println("while循环前,等待前端推送数据。。。。。。。。。。。。"); while((hasRedad = is.read(buff))>0){//判断循环读取 System.out.println("后台接收到值,进入While循环处理"); /* * 因为WebSocket发送过来的数据遁寻了一定的协议格式, 其中第3~6个字节是数据掩码, * 从第七个字节开始才是真正的有效数据。 因此程序使用第3~6个字节对后面的数据进行了处理 */ for (int i = 0; i < hasRedad - 6; i++) { buff[i + 6] = (byte) (buff[i % 4 + 2] ^ buff[i + 6]); } //获得从浏览器发送过来的数据 String pushMsg = new String(buff,6,hasRedad - 6, "utf-8");//第一个值要读取的字节,从第几个开始读取,字符串的总长度,字符集 //便利Socket集合,向每个Socket对象发送信息 for (Iterator<Socket> it = ServerSocketTest.clientSocket.iterator();it.hasNext(); ) { try { Socket s = it.next(); byte[] pushHead = new byte[2]; pushHead[0] = buff[0]; pushHead[1] = (byte) pushMsg.getBytes("utf-8").length; //发送前两个字节 s.getOutputStream().write(pushHead); //发送有效数据 s.getOutputStream().write(pushMsg.getBytes("utf-8")); } catch (SocketException e) { //如果捕获到异常将其从集合中删除 // 如果捕捉到异常,表明该Socket已经关闭 it.remove(); } } } } } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); }finally{ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } // 获取WebSocket请求的Seckey private String getSecWebSocketKey(String req) { // 构建正则表达式,获取Sec-WebSocket-Key:后面的内容 Pattern p = Pattern.compile("^(Sec-WebSocket-Key:).+", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); Matcher m = p.matcher(req); if (m.find()) { // 提取Sec-WebSocket-Key String foundstring = m.group(); return foundstring.split(":")[1].trim(); } else { return null; } } // 根据WebSocket请求的Seckey计算SecAccept private String getSecWebSocketAccept(String key) throws Exception { String guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; key += guid; MessageDigest md = MessageDigest.getInstance("SHA-1"); md.update(key.getBytes("ISO-8859-1"), 0, key.length()); byte[] shalHash = md.digest(); BASE64Encoder encoder = new BASE64Encoder(); return encoder.encode(shalHash); } } ``` 刚才又调试了几次,发现了一些新的东西。 同时开启多个页面进行程序测试。当其中一个页面关闭时,这个页面向后台发送了一条数据,后台接收后处理并发送给其他页面。但是这个页面关闭了,本线程下发送给其他页面的信息全部发送失败。由于发送信息发送不出去,本线程就在此处 ``` } catch (SocketException e) { //如果捕获到异常将其从集合中删除 // 如果捕捉到异常,表明该Socket已经关闭 it.remove(); } ``` 把其他的Socket对象全部删除了,导致所有的Socket对象连接都断开了。求教大神们有没有什么靠谱的解决办法
java 关于NIO实现UDP数据传输问题 ,急谢谢,C币不足请不要介意
各位大侠好,小弟想问一下问题,搞了一两天没有搞明白的。因为要实现一个UDP传输服务端,于是在网上找了很多资料然后就写了一个。但是写好之后发现有两个很严重的问题,希望各位大哥给点意见或者思路去解决。 问题一:启动服务端,同时也启动客户端,客户端传输数据服务器正常接收,但是断开客户端后,再启动客户端,服务器就收不到任何客户端发送的消息,好像是服务器关闭了UDP一样,但是重启服务器后(重新打开UDP)客户端既可以发送信息过来。 问题二:多个客户端。第一个客户端连接上后,第二个客户端怎么也链接不上了。即使关闭了第一个客户端也一样。 如下是代码: package com.gateway.socket; import java.io.IOException; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.nio.channels.DatagramChannel; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.util.Iterator; import java.util.Set; import org.apache.log4j.Logger; public class UDPEchoServerSelector extends Thread { private static final Logger log = Logger.getLogger(ServerSocket.class); // private InetSocketAddress inetSocketAddress; // socket处理类 private UDPSocketHandler handler = new UDPSocketHandler(); // 注册的接受服务 private SocketReceiver receiver = null; /** * 初始化socket * * @param receiver * @param hostname * @param port * @throws IOException * @throws UnknownHostException */ public UDPEchoServerSelector(SocketReceiver receiver, String hostname, int port) { if (hostname.isEmpty()) { inetSocketAddress = new InetSocketAddress(port); } else { inetSocketAddress = new InetSocketAddress(hostname, port); } this.receiver = receiver; } @Override public void run() { try { Selector selector = Selector.open(); // 创建选择器,可以处理多路通道。 DatagramChannel serverSocketChannel = DatagramChannel.open(); // 打开通道 serverSocketChannel.configureBlocking(false); // 非阻塞 serverSocketChannel.socket().bind(inetSocketAddress); /* * 将通道管理器和该通道绑定,并为该通道注册SelectionKey.OP_READ事件,注册该事件后, * 当该事件到达时,selector.select()会返回,如果该事件没到达selector.select()会一直阻塞。 */ serverSocketChannel.register(selector, SelectionKey.OP_READ, new ClientData()); log.info("Server: socket server started."); /* * 采用轮询的方式监听selector上是否有需要处理的事件,如果有,则进行处理 */ while (true) { // 轮询 // 当注册的事件到达时,方法返回;否则,该方法会一直阻塞 int nKeys = selector.select(); if (nKeys == 0) { continue; } // 得到选择键列表 Set Keys = selector.selectedKeys(); Iterator it = Keys.iterator(); while (it.hasNext()) { SelectionKey key = null; key = (SelectionKey) it.next(); // 键为位掩码 it.remove(); // 客户端请求连接事件 if (key.isValid() && key.isWritable()) { log.info("Server: SelectionKey is acceptable."); handler.handleWrite(key); } if (key.isReadable()) {// 获得了可读的事件 log.info("Server: SelectionKey is readable."); handler.receiveMsg(key, receiver); } } Keys.clear(); } } catch (IOException e) { e.printStackTrace(); } } public static class ClientData { public SocketAddress clientAddress; public ByteBuffer buffer = ByteBuffer.allocate(255); } } package com.gateway.socket; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.DatagramChannel; import java.nio.channels.SelectionKey; import org.apache.log4j.Logger; import com.gateway.common.DeviceDataTools; import com.gateway.common.data.HexUtils; import com.gateway.socket.UDPEchoServerSelector.ClientData; /** * * 处理socket类 * * @author Andy * */ public class UDPSocketHandler { private static Logger log = Logger.getLogger(UDPSocketHandler.class); /** * 链接请求 * * @throws IOException */ public void handleWrite(SelectionKey key) { try { DatagramChannel channel = (DatagramChannel) key.channel(); ClientData clntDat = (ClientData) key.attachment(); clntDat.buffer.flip(); // 从起始位置开始发送 int bytesSent; bytesSent = channel.send(clntDat.buffer, clntDat.clientAddress); if (bytesSent != 0) { key.interestOps(SelectionKey.OP_READ); // 关注客户端发送数据 } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 读请求 * * @throws IOException */ public void receiveMsg(SelectionKey key, SocketReceiver receiver) { ByteBuffer byteBuffer = ByteBuffer.allocate(1024); byteBuffer.clear(); DatagramChannel socketChannel = (DatagramChannel) key.channel(); //非阻塞 try { socketChannel.configureBlocking(false); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } System.out.println("channel code:" + socketChannel.hashCode()); try { while (true) { InetSocketAddress client = (InetSocketAddress) socketChannel .receive(byteBuffer); byteBuffer.flip(); // byteBuffer中传过来的是10进制的bytep[] byte[] dst = new byte[byteBuffer.limit()]; byteBuffer.get(dst); // 将10进制的byte[]转化成16进制字符串 String data = HexUtils.converBytesToHex(dst); System.out.println(data); log.info("Server: data1 = " + data); byteBuffer.clear(); receiver.udpreceive(socketChannel, data, client); break; } } catch (java.io.IOException e) { //e.printStackTrace(); //this.closeChannel(key, socketChannel); } catch (Exception e) { //e.printStackTrace(); //this.closeChannel(key, socketChannel); } } /** * * @param socketChannel */ private void closeChannel(SelectionKey key, DatagramChannel socketChannel) { try { while (socketChannel.isOpen()) { key.cancel(); socketChannel.close(); } } catch (IOException e1) { e1.printStackTrace(); } } /** * 根据socketKey从内存中获取channel,通过channel向client端发送消息 * * @param socketKey * 内存在channel对应的key * @param data * 发送的数据 * @return * @throws IOException */ public static boolean send(String socketKey, String data) throws IOException { DatagramChannel socketChannel = SocketChannelMapper .getUDPChannel(socketKey); if (socketChannel == null || !socketChannel.isOpen()) { return false; } InetSocketAddress client = SocketChannelMapper .getUDPInetSocketAddress(socketKey + "address"); boolean f = socketChannel.isConnected(); ByteBuffer byteBuffer = ByteBuffer.wrap(DeviceDataTools.hex2Byte(data)); if (f) { socketChannel.write(byteBuffer); } else { socketChannel.connect(new InetSocketAddress(client.getAddress(), client.getPort())); socketChannel.send(byteBuffer, client); } return true; } /** * 根据socketKey从内存中获取channel,通过channel向client端发送消息 * * @param socketKey * 内存在channel对应的key * @param data * 发送的数据 * @return * @throws IOException */ public static boolean send(DatagramChannel socketChannel, String data, InetSocketAddress client) throws IOException { if (socketChannel == null) { return false; } System.out.println("#########################ADDRESS" + client.getAddress()); System.out.println("#########################PORT" + client.getPort()); boolean f = socketChannel.isConnected(); ByteBuffer byteBuffer = ByteBuffer.wrap(DeviceDataTools.hexStr2ByteArray(data)); if (f) { socketChannel.write(byteBuffer); } else { socketChannel.connect(new InetSocketAddress(client.getAddress(), client.getPort())); socketChannel.send(byteBuffer, client); } return true; } }
webSocket客户端报302,不知道哪里写错了。
请看下面代码: ``` <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!doctype html> <html> <head> <meta charset="UTF-8" content="text/html"> <meta name="Keywords" content=""> <meta name="Description" content=""> <title>基于Java服务端消息主动推送技术</title> <style type="text/css"> *{ margin:0; padding:0; } body{ background:url("image/bg.jpg") no-repeat; background-size:cover; } .chatbox{ width:700px; height:500px; margin:100px auto; font-size:12px; font-family:"微软雅黑"; color:#666; } h1{ text-align:center; font-size:30px; color:green; text-shadow:5px 10px 10px #111; } .chatbox .c_info{ text-align:left; line-height:46px; } .inputText{ height:30px; border:0; outline:none; text-indent:1em; font-size:14px; font-family:"微软雅黑"; color:#61B52D; border: 1px solid #61B52D; } .btn{ width:80px; text-indent:0; background:#9AD02D; color:#fff; margin-left: 10px; } .chatbox .c_message{ width:97%; height:300px; overflow:auto; border:1px solid yellow; font-size:24px; color:#9DA791; padding-left:20px; box-shadow:2px 10px 10px #111; /* background: #EAF9BE; */ } .chatbox .c_send{ margin-top: 10px; } </style> </head> <body> <div class="chatbox"> <h1>基于Java服务端消息主动推送技术</h1> <div class="c_info"> 服务器地址:<input type="text" value="localhost:8080/webSocket" id="addr" class="inputText" style="width:350px"/> 用户名:<input type="text" value="Yinwq" id="userName" class="inputText"/> <input type="button" id="con" class="inputText btn" value="连接" /> </div> <div class="c_message"> </div> <div class="c_send"> <input type="text" id="sendText" class="inputText" style="width:592px" /> <input type="button" id="sendBtn" class="inputText btn" value="发送" /> </div> </div> </body> <!-- 引入jquery类库 --> <script type="text/javascript" src="js/jquery-1.11.2.min.js"></script> <script type="text/javascript"> var connected = false; var ws; $(function(){ $(".c_send").hide(); //1.判断浏览器是否支持webSocket if(window.WebSocket || window.MozWebSocket){ printMsg("您的浏览器支持WebSocket,您可以尝试连接到聊天服务器!" , "OK"); }else{ printMsg("您的浏览器不支持WebSocket,您可以换其他浏览器!" , "ERROR"); $("#con").attr("disabled","true"); } }) //打印信息 function printMsg(msg,msgType){ if(msgType == "OK"){ msg = "<span style='color:green'>"+msg+"</span>"; } if(msgType == "ERROR"){ msg = "<span style='color:red'>"+msg+"</span>" } $(".c_message").append(msg + "<br/>"); } //点击连接的时候触发事件 $("#con").click(function(){ if(connected){ //已连接 ws.send("["+$("#userName").val()+"]离开了聊天室"); connected = false; ws.close(); }else{//没有连接 printMsg("正在准备连接,请稍等!", ""); var url = "ws://"+ $("#addr").val(); if("WebSocket" in window){ //ws = new WebSocket(url); ws = new WebSocket('ws://localhost:8080/webSocket'); }else if ("MozWebSocket" in window) { ws = new MozWebSocket(url); } //连接成功后设置连接状态 connected = true; $("#con").val("断开"); //注册事件 ws.onopen = function(event){ openWs(event); }; ws.onmessage = function(event){ msgWs(event); }; ws.onclose = function(event){ closeWs(event); }; ws.onerror = function(event){ errorWs(event); }; } }); //打开socket function openWs(event){ printMsg("连接已建立...!", "OK"); //建立连接的时候 ws.send("["+$("#userName")+"]进入了聊天室"); $(".c_send").show(); }; //接收消息 function msgWs(event){ printMsg(evnet.data); }; //关闭连接 function closeWs(event){ $("#con").val("连接"); //隐藏发送div $(".c_send").hide(); }; //产生错误 function errorWs(event){ printMsg("与服务器连接错误.." , "ERROR"); }; //点击发送触发事件 $("#sendBtn").click(function(){ //获取发送内容 var text = $("#sendText").val(); ws.send($("#userName").val() + "说:" + text); $("#sendText").val("");//清空发送框 }); </script> </html> ``` 浏览器报错 ![图片说明](https://img-ask.csdn.net/upload/201601/11/1452477841_505407.png) ![图片说明](https://img-ask.csdn.net/upload/201601/11/1452477853_561170.png)
netty ssl加密传输自动断开
netty的客户端和服务端已经完成ssl认证,传输数据4-5次以后自动断开,请各位帮忙看看哪有问题,下面是代码和异常 客户端: 1. 注册client的handler部分代码: SSLEngine sse = client_context.createSSLEngine(); sse.setUseClientMode(true); sc.pipeline().addLast(new ClientOutboundHandler()) .addLast(new SslHandler(sse)) // .addLast(new IdleStateHandler(30, 30, 0, // TimeUnit.SECONDS)) // .addLast(new HeartBeatHandler()) // .addLast(new ClientCodec()) .addLast(new ClientInboundHandler()) .addLast(new ClientLogicHandler()); 2. ClientInboundHandler中发送数据代码: @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) { if (evt instanceof SslHandshakeCompletionEvent) {// 测试ssl加密传输数据 logger.info("client's ssl connection was complated"); ClientSendHeartbeatTask csht = new ClientSendHeartbeatTask(ctx); Thread heartbeatThread = new Thread(csht); heartbeatThread.start(); ClientSendDataTask csdt = new ClientSendDataTask(ctx); Thread dataThread = new Thread(csdt); dataThread.start(); } } 3. 其中ClientSendDataTask的代码如下: @Override public void run() { while (true) { ByteBuf buff = Unpooled.buffer(); String str = JSONArray.fromObject(etlservice.getEtlTablePojos()).toString(); NioMessage nm = new NioMessage(); nm.setType(Constance.DEMODATA_MSG_TYPE); nm.setJson(str); String jsonStr = JacksonUtil.getJsonStr(nm); buff.writeInt(jsonStr.getBytes().length).writeBytes(jsonStr.getBytes()); ctx.writeAndFlush(buff); // buff.clear(); // buff.release(); logger.info("client ClientSendDataTask : send data msg to server"); try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } } } 4. server端注册handler代码: SSLEngine sse = server_context.createSSLEngine(); sse.setNeedClientAuth(true); sse.setUseClientMode(false); sc.pipeline().addLast(new ServerOutboundHandler()) .addLast(new SslHandler(sse)) // .addLast(new IdleStateHandler(30, 30, // 0,TimeUnit.SECONDS)) // .addLast(new HeartBeatHandler()) // .addLast(new ServerCodec()) .addLast(new ServerInboundHandler()) .addLast(new ServerLogicHandler()); 5. ServerInboundHandler中处理接收的数据代码: @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { NioMessage nm = NettyUtil.getNioMessage(msg); if (0 == nm.getType()) logger.warn("server channelRead : msg type is zero , throw exception"); try { if (Constance.HEARTBEAT_MSG_TYPE == nm.getType()) { logger.info("server channelRead : heartbeat msg"); HeartBeatEntity hb = JacksonUtil.getObjMapper().readValue(nm.getJson(), HeartBeatEntity.class); ctx.fireChannelRead(hb); } else if (Constance.DEMODATA_MSG_TYPE == nm.getType()) { logger.info("server channelRead : data msg"); // List<EtlTablePojo> pojoList = (List<EtlTablePojo>) // JacksonUtil.getObjMapper().readValue(nm.getJson(), // List.class); System.out.println("=====json is : " + nm.getJson()); ctx.fireChannelRead(nm.getJson()); } else if (Constance.RESULT_MSG_TYPE == nm.getType()) { logger.info("server channelRead : operation result msg"); ResultEntity re = JacksonUtil.getObjMapper().readValue(nm.getJson(), ResultEntity.class); re.toString(); } } catch (JsonParseException e) { e.printStackTrace(); } catch (JsonMappingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } 6. 运行一段时间后出现错误如下: [nioEventLoopGroup-14-1] DEBUG io.netty.handler.ssl.SslHandler - Swallowing a harmless 'connection reset by peer / broken pipe' error that occurred while writing close_notify in response to the peer's close_notify java.io.IOException: Connection reset by peer at sun.nio.ch.FileDispatcher.read0(Native Method) ~[na:1.6.0_65] at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:21) ~[na:1.6.0_65] at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:198) ~[na:1.6.0_65] at sun.nio.ch.IOUtil.read(IOUtil.java:166) ~[na:1.6.0_65] at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:245) ~[na:1.6.0_65] at io.netty.buffer.UnpooledUnsafeDirectByteBuf.setBytes(UnpooledUnsafeDirectByteBuf.java:436) ~[netty-all-4.0.11.Final.jar:na] at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:870) ~[netty-all-4.0.11.Final.jar:na] at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:208) ~[netty-all-4.0.11.Final.jar:na] at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:88) ~[netty-all-4.0.11.Final.jar:na] at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:485) [netty-all-4.0.11.Final.jar:na] at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:452) [netty-all-4.0.11.Final.jar:na] at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:346) [netty-all-4.0.11.Final.jar:na] at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:101) [netty-all-4.0.11.Final.jar:na] at java.lang.Thread.run(Thread.java:695) [na:1.6.0_65]
关于java聊天室,求助
问题: 服务器端退出,线程却还在运行 报错: java.net.SocketException: Socket closed at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.read(SocketInputStream.java:152) at java.net.SocketInputStream.read(SocketInputStream.java:122) at java.net.SocketInputStream.read(SocketInputStream.java:210) at java.io.DataInputStream.readUnsignedShort(DataInputStream.java:337) at java.io.DataInputStream.readUTF(DataInputStream.java:589) at java.io.DataInputStream.readUTF(DataInputStream.java:564) at talkingRoom.Servicer$1.run(Servicer.java:127) *********客户端************************ import java.awt.*; import java.net.*; import java.awt.event.*; import java.io.*; import javax.swing.*; @SuppressWarnings("serial") public class Desktop extends JFrame implements ActionListener { @SuppressWarnings("unused") private class WindowCloser extends WindowAdapter { public void windowClosing(WindowEvent we) { System.exit(0); } } private Socket cs = null; private JPanel p = new JPanel(); private JTextArea output = new JTextArea(); private JTextField input = new JTextField(); private DataOutputStream dos; private DataInputStream dis; private JButton b1 = new JButton("进入"); private JButton b2 = new JButton("退出"); private JLabel fuwuqis = new JLabel("服务器:"); private JTextField fuwuqi = new JTextField("127.0.0.1"); private JLabel duankous = new JLabel("端口:"); private JTextField duankou = new JTextField("8888"); private JLabel nichengs = new JLabel("昵称:"); private JTextField nicheng = new JTextField("游客1"); private JButton b3 = new JButton("发送"); private String talking; private boolean started = false; private boolean bConnected = false; //UI界面(不需要再修改) Desktop() { p.setLayout(new BorderLayout()); JPanel p1 = new JPanel(); JPanel p2 = new JPanel(); p1.add(b1); b1.addActionListener(this); p1.add(b2); b2.addActionListener(this); p1.add(fuwuqis); p1.add(fuwuqi); p1.add(duankous); p1.add(duankou); p1.add(nichengs); p1.add(nicheng); p2.setLayout(new BorderLayout()); p2.add(input, BorderLayout.CENTER); p2.add(b3, BorderLayout.EAST); b3.addActionListener(this); p.add(p1, BorderLayout.NORTH); p.add(p2, BorderLayout.SOUTH); p.add(output, BorderLayout.CENTER); buttonclose(); this.setTitle("聊天室for客户端"); this.add(p); this.setSize(500, 300); this.setVisible(true); } public void buttonclose() { b1.setEnabled(true); b2.setEnabled(false); b3.setEnabled(false); input.setEditable(false); fuwuqi.setEditable(true); duankou.setEditable(true); nicheng.setEditable(true); } public void buttonopen() { b1.setEnabled(false); b2.setEnabled(true); b3.setEnabled(true); input.setEditable(true); fuwuqi.setEditable(false); duankou.setEditable(false); nicheng.setEditable(false); } //连接函数,流与Socket所在 public void connect() { try { cs = new Socket(fuwuqi.getText(), Integer.parseInt(duankou.getText())); System.out.print("加入连接"); dos = new DataOutputStream(cs.getOutputStream()); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } //断开函数,流与Socket所在 public void disconnect() { try { bConnected = false; dos.writeUTF("$%$"); dis.close(); dos.close(); System.out.println("disdos.close"); cs.close(); System.out.println("cs.close"); output.append("退出成功\n"); buttonclose(); } catch (IOException e) { e.printStackTrace(); } } //发送流函数 public void send() { try { if(talking == null) { dos.writeUTF(""); }else { dos.writeUTF(talking); } dos.flush(); } catch (IOException e1) { e1.printStackTrace(); } } //接收流函数 public void receive() { try { started = true; bConnected = true; dis = new DataInputStream(cs.getInputStream()); new Thread() { public void run() { System.out.println("开始接收"); while (bConnected) { String talking = ""; try { talking = dis.readUTF(); output.append("\n\r" + "主机" + " : " + talking); if("$%$".equalsIgnoreCase(talking)){ disconnect(); } } catch (IOException e) { e.printStackTrace(); } } // try { // dis.close(); // } catch (IOException e) { // e.printStackTrace(); // } } }.start(); } catch (IOException e1) { e1.printStackTrace(); } } public void actionPerformed(ActionEvent e) { String S = e.getActionCommand(); if ("发送".equalsIgnoreCase(S)) { talking = input.getText().trim(); String snicheng = nicheng.getText().trim(); output.append("\n\r" + snicheng + " : " + talking); input.setText(""); try { dos.writeUTF(snicheng); } catch (IOException e1) { e1.printStackTrace(); } send(); } else if ("进入".equalsIgnoreCase(S)) { connect(); receive(); output.append("进入成功\n 服务器:" + fuwuqi.getText() + "\t端口:" + duankou.getText() + "\t昵称:" + nicheng.getText() + "\n"); buttonopen(); } else if ("退出".equalsIgnoreCase(S)) { disconnect(); } } public static void main(String args[]) { new Desktop(); } } ***********服务器******************************** import java.awt.*; import java.awt.event.*; import java.io.*; import java.net.*; import javax.swing.*; @SuppressWarnings("serial") public class Servicer extends JFrame implements ActionListener { @SuppressWarnings("unused") private class WindowCloser extends WindowAdapter { public void windowClosing(WindowEvent we) { System.exit(0); } } private ServerSocket ss = null; private Socket s; private JPanel p = new JPanel(); private JTextArea output = new JTextArea(); private JTextField input = new JTextField(); private DataOutputStream dos; private DataInputStream dis; private JButton b1 = new JButton("启动"); private JButton b2 = new JButton("退出"); private JButton b3 = new JButton("发送"); private String talking, nicheng; private boolean started = true; private boolean bConnected = false; // UI界面(不需要再修改) Servicer() { p.setLayout(new BorderLayout()); JPanel p1 = new JPanel(); JPanel p2 = new JPanel(); p1.add(b1); b1.addActionListener(this); p1.add(b2); b2.addActionListener(this); b3.addActionListener(this); p2.setLayout(new BorderLayout()); p2.add(input, BorderLayout.CENTER); p2.add(b3, BorderLayout.EAST); p.add(p1, BorderLayout.NORTH); p.add(p2, BorderLayout.SOUTH); p.add(output, BorderLayout.CENTER); b2.setEnabled(false); b1.setEnabled(true); b3.setEnabled(false); input.setEditable(false); output.setEditable(false); this.setTitle("聊天室for服务端"); this.add(p); this.setSize(500, 300); this.setVisible(true); } public void buttonclose() { b1.setEnabled(true); b2.setEnabled(false); b3.setEnabled(false); input.setEditable(false); } public void buttonopen() { b1.setEnabled(false); b2.setEnabled(true); b3.setEnabled(true); input.setEditable(true); } public void disconnect() { started = false; bConnected = false; try { dos.writeUTF("$%$"); dos.close(); dis.close(); s.close(); System.out.println("Servicer dos.close"); ss.close(); System.out.println("Servicer cs.close"); } catch (IOException e) { e.printStackTrace(); } } public void start() { try { ss = new ServerSocket(8888); } catch (IOException e) { e.printStackTrace(); } try { started = true; //while(started){ s = ss.accept(); output.append("新加入,已连接"); buttonopen(); bConnected = true; dos = new DataOutputStream(s.getOutputStream()); dis = new DataInputStream(s.getInputStream()); link(); //} } catch (IOException e1) { e1.printStackTrace(); } } public void send() { talking = input.getText().trim(); try { if(talking == null) { dos.writeUTF(""); } else { dos.writeUTF(talking); } dos.flush(); } catch (IOException e1) { e1.printStackTrace(); } } public void link() { new Thread(){ public void run() { String nicheng = null; try { nicheng = dis.readUTF(); } catch (IOException e1) { output.append("\n\r用户名获取异常"); e1.printStackTrace(); } while (bConnected) { String talking = ""; try { talking = dis.readUTF(); } catch (IOException e) { e.printStackTrace(); } if("$%$".equalsIgnoreCase(talking)){ disconnect(); } output.append("\n\r" + nicheng + " : " + talking); } // try { // dis.close(); // } catch (IOException e) { // e.printStackTrace(); // } } }.start(); } public void actionPerformed(ActionEvent e) { String S = e.getActionCommand(); String takeing = input.getText().toString(); if ("启动".equalsIgnoreCase(S)) { start(); } else if ("退出".equalsIgnoreCase(S)) { disconnect(); output.append("退出成功"); } else if ("发送".equalsIgnoreCase(S)) { send(); output.append("\n\r" + "主机" + " : " + takeing); input.setText(""); } } public static void main(String args[]) { new Servicer(); } }
怎么能观察出JVM的Old区中存储的都是那些对象
操作系统:Solaris10 JDK:SUN JDK1.5.0_17 [b]问题补充:[/b] jmap这个命令我用了,但我发现只是显示出了实例的数量。看不出来哪些对象是在Old区的。你说用Heap工具分析,是什么Heap工具呢?我用了Optimizeit,也是只能看出实例的数量和引用关系,看不出哪些对象是在Old区的。 [b]问题补充:[/b] 我现在的GC策略是这样的,堆最大,最小都是1024m,young区是512m,对象在from和to之间拷贝5次然后扔到old区。回收算法用的是cms。我们的应用对吞吐量的要求比较高,绝大多数都是短生命周期的对象。我在windows下用optimizeit检查了,不存在内存泄漏,但发现在并发量比较大的时候,有几个对象的实例数量是一直在增长的。但当客户端的程序停止的时候,这些对象又是可以被回收的。我们的程序是运行在solaris上的,由于我没下载到optimizeit的solaris安装文件,或者是类似工具的solaris安装文件,因此不确定,olc区中的那些对象是否就是那几个不断增长的对象。我用jvmstat看了,old区涨的很快。而且程序运行大概20分钟左右就core dump了。有的时候会直接把服务器整死。因此我想看看有没有什么手段来看看old区的对象存储的都是什么来帮我肯定一下,就是那几个对象再搞鬼。 [b]问题补充:[/b] 其实这个问题,在昨天临下班之前的10几分钟突然有了进展。终于排查出,我们的程序是没有内存泄漏的。而是由于传输层的拥挤造成的。设置了socket的readReceiveBuffer和sendBuffer之后这个问题得到了缓解。但是为什么会因为传输层的拥挤导致我们old区的对象很多,这点需要再好好研究一下mina框架。 [b]问题补充:[/b] [quote]根据你的说法, 我觉得你的,配置有问题的, 为什么设计-Xmn512m, 这个是很关键的, 如果你要求很低的world stop. 那么把-Xmn设置到128 或者256m, core dump 的原因可能是因为你CMS机制不起作用, 导致并行收集过多产生的。 另外,也跟你的JAVA的版本有关系。 CMS最好使用JAVA6的版本, 在JAVA5上, 这个技术并不是非常成熟。如果是JAVA5, CMS的启动策略是有BUG的, 这个你可以参考我的BLOG : http://sdh5724.iteye.com/admin/blogs/283977 [/quote] young区默认的大小是堆的1/4,但是对于吞吐量优先的程序,可以设置为堆的1/2。因为对象的生命周期短,应该尽可能的让对象在young区就被回收掉,免得被拷贝到old区,再进行回收时,暂停时间会相对较长。网上有些资料显示了,对于吞吐量优先的程序,应该设置一个较大的young区的说法,Sun的网站上也有,将堆设置为3G,young区设置为2G的例子。你说的CMS最好在JAVA6下用,这个我真的不知道。听说JAVA6的GC机制要比JAVA5好。这个我回去试试。 [quote]readReceiveBuffer和sendBuffer 是操作系统参数, 如果你的OS内存很紧张, 也可能导致系统资源不够。 这个参数应该调整成你业务需要的发送接收的大小, 不可以盲目扩大, 每个TCP连接都会占用这个BUFF的大小。 我建议你一般设置成8K。[/quote] 你说的这个我很关系,对这两个参数我也不太了解,但的确是缓解了问题,而且很明显。目前我们只使用了一个TCP连接。对于你说的“这个参数应该调整成你业务需要的发送接收的大小”,我不太明白是什么意思。主要是我不清楚我们需要的大小是多少啊,呵呵。你说的8K,这个是默认配置。但我们使用这个配置时,程序最多只能跑20分钟,程序就死掉了。这涉及到tcp的传输,因为跟我们对接的另一端,他们是C语言写的,目前他们没有设置缓冲区大小,应该用的也是默认的,但C程序我不太了解,不知道是多少。我把这个缓冲区设置为Integer的最大值了,好像是2G(我也觉得有点儿夸张),程序大概跑了四十分钟,服务器宕机了。 [quote]我觉得, 你是不是因为TCP的连接断开后, 没有释放TCP连接? socket.close(). 会导致大量的time_wait的连接, 你要仔细看下。 OS会在比较长的时间回收[/quote] 我们现在就一个TCP链接,出现问题时,链接没断过。我们应该是没有内存泄漏的,我用Optimizeit检查了好多次了。 很高兴与你讨论这个问题,我感觉现在问题出现在TCP的缓冲区上,应该让C那边也设置一个较大的缓冲区,然后再看看问题能不能得到解决。 [b]问题补充:[/b] 经过几天的测试,总结如下: 1.机器宕机居然是机器的问题,那个机器,不管上面运行的是我们的应用程序还是模拟器,都会宕机。换了其他的几台服务器,都没出现宕机的问题。 2.buffer的设置:我们一个消息的长度是20个字节。每秒钟2000条消息,就是40000个字节,因次buffer设置为40000。但最后还是没有设置这个值采用默认的。因为问题可能不在这里。 3.目前的问题,使用mina的client接收消息时,每秒钟2000条,大概运行一段时间之后,就会mina就会接收到一个很大的包(100K以上)。这导致我们应用层解析这个消息的时候调用层次过多,抛出stackOverFlow的异常,并且主动把连接关闭了。其实,我们可以修改一下我们的代码,避免抛出这个异常。但这不是问题的根源,因为mina传了一个这么大的数据包给应用层就是不正常的。于是我看了一下mina的代码,在read的时候,会根据接收到的消息的长度,来调整allocate的长度。这个上限是receiveByteBuffer的2倍。我尝试修改了mina的代码,让他每次固定allocate 1024个字节。但是问题依然存在,目前没找到解决方法。为了规避这个问题,只是让服务端不给我们发送这个应答,这在业务上是允许的。但没找到问题的根源总是感觉心里堵的荒,打算试试grizzly。
130 个相见恨晚的超实用网站,一次性分享出来
相见恨晚的超实用网站 持续更新中。。。
终于明白阿里百度这样的大公司,为什么面试经常拿ThreadLocal考验求职者了
点击上面↑「爱开发」关注我们每晚10点,捕获技术思考和创业资源洞察什么是ThreadLocalThreadLocal是一个本地线程副本变量工具类,各个线程都拥有一份线程私...
win10系统安装教程(U盘PE+UEFI安装)
一、准备工作 u盘,电脑一台,win10原版镜像(msdn官网) 二、下载wepe工具箱 极力推荐微pe(微pe官方下载) 下载64位的win10 pe,使用工具箱制作启动U盘打开软件, 选择安装到U盘(按照操作无需更改) 三、重启进入pe系统 1、关机后,将U盘插入电脑 2、按下电源后,按住F12进入启动项选择(技嘉主板是F12) 选择需要启...
程序员必须掌握的核心算法有哪些?
由于我之前一直强调数据结构以及算法学习的重要性,所以就有一些读者经常问我,数据结构与算法应该要学习到哪个程度呢?,说实话,这个问题我不知道要怎么回答你,主要取决于你想学习到哪些程度,不过针对这个问题,我稍微总结一下我学过的算法知识点,以及我觉得值得学习的算法。这些算法与数据结构的学习大多数是零散的,并没有一本把他们全部覆盖的书籍。下面是我觉得值得学习的一些算法以及数据结构,当然,我也会整理一些看过...
大学四年自学走来,这些私藏的实用工具/学习网站我贡献出来了
大学四年,看课本是不可能一直看课本的了,对于学习,特别是自学,善于搜索网上的一些资源来辅助,还是非常有必要的,下面我就把这几年私藏的各种资源,网站贡献出来给你们。主要有:电子书搜索、实用工具、在线视频学习网站、非视频学习网站、软件下载、面试/求职必备网站。 注意:文中提到的所有资源,文末我都给你整理好了,你们只管拿去,如果觉得不错,转发、分享就是最大的支持了。 一、电子书搜索 对于大部分程序员...
C语言魔塔游戏
很早就很想写这个,今天终于写完了。 游戏截图: 编译环境: VS2017 游戏需要一些图片,如果有想要的或者对游戏有什么看法的可以加我的QQ 2985486630 讨论,如果暂时没有回应,可以在博客下方留言,到时候我会看到。 下面我来介绍一下游戏的主要功能和实现方式 首先是玩家的定义,使用结构体,这个名字是可以自己改变的 struct gamerole { char n...
java源码分析 Arrays.asList()与Collections.unmodifiableList()
ArrayList支持所有的可选操作(因为一个UnsupportedOperationException异常都没有捕获到),所以要想拥有完备的功能,还是得使用ArrayList啊。 Arrays$ArrayList除了set()操作外,都不支持。 Collections$UnmodifiableRandomAccessList都不支持,名副其实的Unmodifiable不可修改。
究竟你适不适合买Mac?
我清晰的记得,刚买的macbook pro回到家,开机后第一件事情,就是上了淘宝网,花了500元钱,找了一个上门维修电脑的师傅,上门给我装了一个windows系统。。。。。。 表砍我。。。 当时买mac的初衷,只是想要个固态硬盘的笔记本,用来运行一些复杂的扑克软件。而看了当时所有的SSD笔记本后,最终决定,还是买个好(xiong)看(da)的。 已经有好几个朋友问我mba怎么样了,所以今天尽量客观...
Python爬虫爬取淘宝,京东商品信息
小编是一个理科生,不善长说一些废话。简单介绍下原理然后直接上代码。 使用的工具(Python+pycharm2019.3+selenium+xpath+chromedriver)其中要使用pycharm也可以私聊我selenium是一个框架可以通过pip下载 pip installselenium -ihttps://pypi.tuna.tsinghua.edu.cn/simple/ ...
Java学习笔记(七十二)—— Cookie
概述 会话技术: 会话:一次会话中包含多次请求和响应 一次会话:浏览器第一次给服务器发送资源请求,会话建立,直到有一方断开为止 功能:在一次会话的范围内的多次请求间,共享数据 方式: 客户端会话技术:Cookie,把数据存储到客户端 服务器端会话技术:Session,把数据存储到服务器端 Cookie 概念:客户端会话技术,将数据存储到客户端 快速入门: 使用步骤: 创建C...
程序员写了一个新手都写不出的低级bug,被骂惨了。
这种新手都不会范的错,居然被一个工作好几年的小伙子写出来,差点被当场开除了。
Java工作4年来应聘要16K最后没要,细节如下。。。
前奏: 今天2B哥和大家分享一位前几天面试的一位应聘者,工作4年26岁,统招本科。 以下就是他的简历和面试情况。 基本情况: 专业技能: 1、&nbsp;熟悉Sping了解SpringMVC、SpringBoot、Mybatis等框架、了解SpringCloud微服务 2、&nbsp;熟悉常用项目管理工具:SVN、GIT、MAVEN、Jenkins 3、&nbsp;熟悉Nginx、tomca...
2020年,冯唐49岁:我给20、30岁IT职场年轻人的建议
点击“技术领导力”关注∆每天早上8:30推送 作者|Mr.K 编辑| Emma 来源|技术领导力(ID:jishulingdaoli) 前天的推文《冯唐:职场人35岁以后,方法论比经验重要》,收到了不少读者的反馈,觉得挺受启发。其实,冯唐写了不少关于职场方面的文章,都挺不错的。可惜大家只记住了“春风十里不如你”、“如何避免成为油腻腻的中年人”等不那么正经的文章。 本文整理了冯...
程序员该看的几部电影
1、骇客帝国(1999) 概念:在线/离线,递归,循环,矩阵等 剧情简介: 不久的将来,网络黑客尼奥对这个看似正常的现实世界产生了怀疑。 他结识了黑客崔妮蒂,并见到了黑客组织的首领墨菲斯。 墨菲斯告诉他,现实世界其实是由一个名叫“母体”的计算机人工智能系统控制,人们就像他们饲养的动物,没有自由和思想,而尼奥就是能够拯救人类的救世主。 可是,救赎之路从来都不会一帆风顺,到底哪里才是真实的世界?如何...
蓝桥杯知识点汇总:基础知识和常用算法
文章目录基础语法部分:算法竞赛常用API:算法部分数据结构部分 此系列包含蓝桥杯绝大部分所考察的知识点,以及真题题解~ 基础语法部分: 备战蓝桥杯java(一):一般输入输出 和 快速输入输(BufferedReader&amp;BufferedWrite) 备战蓝桥杯java(二):java编程规范和常用数据类型 备战蓝桥杯java(三):常用功能符以及循环结构和分支结构 备战蓝桥杯java(四...
作为一个程序员,CPU的这些硬核知识你必须会!
CPU对每个程序员来说,是个既熟悉又陌生的东西? 如果你只知道CPU是中央处理器的话,那可能对你并没有什么用,那么作为程序员的我们,必须要搞懂的就是CPU这家伙是如何运行的,尤其要搞懂它里面的寄存器是怎么一回事,因为这将让你从底层明白程序的运行机制。 随我一起,来好好认识下CPU这货吧 把CPU掰开来看 对于CPU来说,我们首先就要搞明白它是怎么回事,也就是它的内部构造,当然,CPU那么牛的一个东...
破14亿,Python分析我国存在哪些人口危机!
一、背景 二、爬取数据 三、数据分析 1、总人口 2、男女人口比例 3、人口城镇化 4、人口增长率 5、人口老化(抚养比) 6、各省人口 7、世界人口 四、遇到的问题 遇到的问题 1、数据分页,需要获取从1949-2018年数据,观察到有近20年参数:LAST20,由此推测获取近70年的参数可设置为:LAST70 2、2019年数据没有放上去,可以手动添加上去 3、将数据进行 行列转换 4、列名...
实现简单的轮播图(单张图片、多张图片)
前言 刚学js没多久,这篇博客就当做记录了,以后还会完善的,希望大佬们多多指点。ps:下面出现的都是直接闪动,没有滑动效果的轮播图。 单张图片的替换 · ...
强烈推荐10本程序员在家读的书
很遗憾,这个春节注定是刻骨铭心的,新型冠状病毒让每个人的神经都是紧绷的。那些处在武汉的白衣天使们,尤其值得我们的尊敬。而我们这些窝在家里的程序员,能不外出就不外出,就是对社会做出的最大的贡献。 有些读者私下问我,窝了几天,有点颓丧,能否推荐几本书在家里看看。我花了一天的时间,挑选了 10 本我最喜欢的书,你可以挑选感兴趣的来读一读。读书不仅可以平复恐惧的压力,还可以对未来充满希望,毕竟苦难终将会...
Linux自学篇——linux命令英文全称及解释
man: Manual 意思是手册,可以用这个命令查询其他命令的用法。 pwd:Print working directory 意思是密码。 su:Swith user 切换用户,切换到root用户 cd:Change directory 切换目录 ls:List files 列出目录下的文件 ps:Process Status 进程状态 mkdir:Make directory ...
Python实战:抓肺炎疫情实时数据,画2019-nCoV疫情地图
今天,群里白垩老师问如何用python画武汉肺炎疫情地图。白垩老师是研究海洋生态与地球生物的学者,国家重点实验室成员,于不惑之年学习python,实为我等学习楷模。先前我并没有关注武汉肺炎的具体数据,也没有画过类似的数据分布图。于是就拿了两个小时,专门研究了一下,遂成此文。
智力题(程序员面试经典)
NO.1  有20瓶药丸,其中19瓶装有1克/粒的药丸,余下一瓶装有1.1克/粒的药丸。给你一台称重精准的天平,怎么找出比较重的那瓶药丸?天平只能用一次。 解法 有时候,严格的限制条件有可能反倒是解题的线索。在这个问题中,限制条件是天平只能用一次。 因为天平只能用一次,我们也得以知道一个有趣的事实:一次必须同时称很多药丸,其实更准确地说,是必须从19瓶拿出药丸进行称重。否则,如果跳过两瓶或更多瓶药...
Java与Python学习通法(1)和(2)序言和编程语言发展史怎么学
dd
在家远程办公效率低?那你一定要收好这个「在家办公」神器!
相信大家都已经收到国务院延长春节假期的消息,接下来,在家远程办公可能将会持续一段时间。 但是问题来了。远程办公不是人在电脑前就当坐班了,相反,对于沟通效率,文件协作,以及信息安全都有着极高的要求。有着非常多的挑战,比如: 1在异地互相不见面的会议上,如何提高沟通效率? 2文件之间的来往反馈如何做到及时性?如何保证信息安全? 3如何规划安排每天工作,以及如何进行成果验收? ...... ...
作为一个程序员,内存和磁盘的这些事情,你不得不知道啊!!!
截止目前,我已经分享了如下几篇文章: 一个程序在计算机中是如何运行的?超级干货!!! 作为一个程序员,CPU的这些硬核知识你必须会! 作为一个程序员,内存的这些硬核知识你必须懂! 这些知识可以说是我们之前都不太重视的基础知识,可能大家在上大学的时候都学习过了,但是嘞,当时由于老师讲解的没那么有趣,又加上这些知识本身就比较枯燥,所以嘞,大家当初几乎等于没学。 再说啦,学习这些,也看不出来有什么用啊!...
阿里架构师花近十年时间整理出来的Java核心知识pdf(Java岗)
由于细节内容实在太多啦,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容! 整理了一份Java核心知识点。覆盖了JVM、锁、并发、Java反射、Spring原理、微服务、Zookeeper、数据库、数据结构等大量知识点。 欢迎大家加入java学习交流社区 点击加入 可获取文中文档 小编推荐: ...
Python基础知识点梳理
python常见知识点梳理 摘要: 本文主要介绍一些平时经常会用到的python基础知识点,用于加深印象。python的详细语法介绍可以查看官方编程手册,也有一些在线网站对python语法进行了比较全面的介绍,比如菜鸟教程: python3 教程|菜鸟教程 本文主要是介绍基础语法,操作实例在另一篇博客中单独介绍: python语言介绍 python是一门解释型语言,python的设计目标: 一门...
2020年2月全国程序员工资统计,平均工资13716元
趋势 2020年2月,中国大陆程序员平均工资13716员,比上个月增加。具体趋势如图: 各主要程序员城市工资变化 城市 北京,上海,深圳,杭州,广州四地的工资最高。 city 平均工资 最低工资 中位数 最高工资 招聘人数 百分比 北京 18098 3750 15000 45000 20529 9.53% 深圳 16903 5750 15000 37500 30941 1...
Java坑人面试题系列: 包装类(中级难度)
Java Magazine上面有一个专门坑人的面试题系列: https://blogs.oracle.com/javamagazine/quiz-2。 这些问题的设计宗旨,主要是测试面试者对Java语言的了解程度,而不是为了用弯弯绕绕的手段把面试者搞蒙。 如果你看过往期的问题,就会发现每一个都不简单。 这些试题模拟了认证考试中的一些难题。 而 “中级(intermediate)” 和 “高级(ad...
为什么说程序员做外包没前途?
之前做过不到3个月的外包,2020的第一天就被释放了,2019年还剩1天,我从外包公司离职了。我就谈谈我个人的看法吧。首先我们定义一下什么是有前途 稳定的工作环境 不错的收入 能够在项目中不断提升自己的技能(ps:非技术上的认知也算) 找下家的时候能找到一份工资更高的工作 如果你目前还年轻,但高不成低不就,只有外包offer,那请往下看。 外包公司你应该...
基于Python的人脸自动戴口罩系统
目录 1、项目背景 2、页面设计 3、器官识别 4、退出系统 1、项目背景 2019年新型冠状病毒感染的肺炎疫情发生以来,牵动人心,举国哀痛,口罩、酒精、消毒液奇货可居。 抢不到口罩,怎么办?作为技术人今天分享如何使用Python实现自动戴口罩系统,来安慰自己,系统效果如下所示: 本系统的实现原理是借助 Dlib模块的Landmark人脸68个关键点检测库轻松识别出人脸五官...
这个世界上人真的分三六九等,你信吗?
偶然间,在知乎上看到一个问题 一时间,勾起了我深深的回忆。 以前在厂里打过两次工,做过家教,干过辅导班,做过中介。零下几度的晚上,贴过广告,满脸、满手地长冻疮。 再回首那段岁月,虽然苦,但让我学会了坚持和忍耐。让我明白了,在这个世界上,无论环境多么的恶劣,只要心存希望,星星之火,亦可燎原。 下文是原回答,希望能对你能有所启发。 如果我说,这个世界上人真的分三六九等,...
Java基础知识点梳理
虽然已经在实际工作中经常与java打交道,但是一直没系统地对java这门语言进行梳理和总结,掌握的知识也比较零散。恰好利用这段时间重新认识下java,并对一些常见的语法和知识点做个总结与回顾,一方面为了加深印象,方便后面查阅,一方面为了掌握好Android打下基础。
jQuery实现高仿QQ音乐
几个实现的效果看视频吧: 动图很是不清楚 代码: html &lt;!DOCTYPE html&gt; &lt;html lang="en"&gt; &lt;head&gt; &lt;meta charset="UTF-8"&gt; &lt;title&gt;music&lt;/title&gt; &lt;link href="../jquery.mCustomScrol...
《请停止无效的努力》读书笔记
一、如何快速找到你的天赋优势 1、人的价值定位 1.1、冰山模型 &nbsp; &nbsp; &nbsp; &nbsp; 你能创造多大的价值,离不开三大内在因素: 第一要素:知识和技能,位于冰山显露的部分,是非常显性,容易展示出来的; 第二要素:能力,比如:思考能力、人际交往能力等,需要通过仔细的行为观察才能看出,位于冰山的中间部分; 第三要素:天赋。包括潜在能力、性格特质、动机、价值观等 ...
2020年全新Java学习路线图,含配套视频,学完即为中级Java程序员!!
新的一年来临,突如其来的疫情打破了平静的生活! 在家的你是否很无聊,如果无聊就来学习吧! 世上只有一种投资只赚不赔,那就是学习!!! 传智播客于2020年升级了Java学习线路图,硬核升级,免费放送! 学完你就是中级程序员,能更快一步找到工作! 一、Java基础 JavaSE基础是Java中级程序员的起点,是帮助你从小白到懂得编程的必经之路。 在Java基础板块中有6个子模块的学...
相关热词 c#导入fbx c#中屏蔽键盘某个键 c#正态概率密度 c#和数据库登陆界面设计 c# 高斯消去法 c# codedom c#读取cad文件文本 c# 控制全局鼠标移动 c# temp 目录 bytes初始化 c#
立即提问