zoukankan      html  css  js  c++  java
  • Java多线程 Socket使用

    点我跳过黑哥的卑鄙广告行为,进入正文。

    Java多线程系列更新中~

      正式篇:

    1. Java多线程(一) 什么是线程
    2. Java多线程(二)关于多线程的CPU密集型和IO密集型这件事
    3. Java多线程(三)如何创建线程
    4. Java多线程(四)java中的Sleep方法
    5. Java多线程(五)线程的生命周期

      番外篇(神TM番外篇):

    1. Java 过一下基础
    2. 转载:java中Thread.sleep()函数使用
    3. Java多线程 Socket使用

    Socket是客户端和服务器端交流的端点。通过它可以实现客户端和服务器端的通信。顺着这篇文章操作下来,你应该会对Socket编程有比较系统的了解。注意,跟着敲代码,有什么不懂而我又没提到的地方,随时百度,不要积累误差。

    客户端编程

    Socket是有连接的,所以双方建立通信,需要知道彼此的网络位置(IP和端口)。

    创建Socket对象:

    Socket socket = new Socket("127.0.0.1",8852);
    • 第一个参数:服务器的IP地址(这里用的是本机地址)
    • 第二个参数:TCP端口号,其中0~1023是系统保留端口。

    为什么需要端口号?例如你想要去找你的暗恋对象告白,你知道她的学校地址(IP地址),但是一个学校不会只有你暗恋对象一个人(一个主机不会只进行一个任务),你需要知道她的宿舍号(端口号),这样才能方便告白。

    使用本机既做客户端,又做服务器是个什么情况?就是你和你暗恋对象在同一个学校,这没什么区别,你仍然需要她的宿舍号(端口号)才能找到她告白(客户端和服务前通信)。

    初始版本代码

    public class MyClient {
        public static void main(String[] args) throws Exception{
        Socket socket = new Socket("127.0.0.1",8852);
        DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
        dataOutputStream.writeUTF("Hello socket");
        socket.close();
        }
    }

    注意别忘了抛出异常,这里只是个演示作用,直接throws Exception了。这里你直接运行肯定是不能建立连接的,因为服务器端还没写。

    这里,假如你知道服务器监听的是8852端口,你创建了一个socket来和它进行通信。socket.getOutputStream()得到这个socket的输出流,当你调用writeUTF()方法时,便会向其中写一个字符串。

    典型三段式要牢记:打开、通信、关闭。

    服务器端编程

    注意了注意了,要开始造女票了。

    初始版本代码

    import java.io.DataInputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class MyServer {
        public static void main(String[] args) throws Exception{
            ServerSocket serverSocket = new ServerSocket(8852);
            System.out.println("Server 等待接收数据~");
            Socket socket = serverSocket.accept();
            DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
            String string = dataInputStream.readUTF();
            System.out.println(string);
            System.out.println("Server 接收数据完毕,拜拜了您~");
            socket.close();
            serverSocket.close();
        }
    }    

    这里服务器端用到了ServerSocket,负责接收客户端的连接请求。你的暗恋对象可能有好多人要向她告白,一个Socket自然无法处理。通过ServerSocket的accept方法从连接请求队列中取出一个进行连接。那这个ServerSocket就是你暗恋对象的室友,帮助她管理诸多“告白”。

    这里只是把服务器端接收到的数据打印了一下便关闭了。至此,一个简单的服务器-客户端通信便建立了。但是这个服务器只能处理一个连接便关闭了,我们可以改进一下。

    往下看之前请确保你大致理解了上述过程,最好自己敲一下代码

    到这里你可能会想,只处理一个就关闭了,那我加个while循环,让它一直运行怎么样?

    听着还可以,那我们来试验一下(下面只是分析一下,不用跟着敲)。

    将服务器端代码更改为:

    while(true)
    {
      Socket socket = serverSocket.accept();
      DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
      String string = dataInputStream.readUTF();
      System.out.println(string);
      socket.close();
      serverSocket.close();
    }     

    这个会出现什么问题?客户端正连着呢,啪,你服务器给人家断开了,而且accept()接受的是socket请求,所以这种情况,除非客户端再连一次,否则二者的通信就断了。

    你可能会说,那我把Socket移到外面呢?

    其实吧,这个仔细理一下就会明白,如果放到外面的话,只要你想接收多个socket,就要把

    Socket socket = serverSocket.accept();放到while循环中,但是你只要把它放到while循环中,它就只能和一个socket进行通信。这里有兴趣可以再查阅一下资料,下面直接进入线程阶段。

    服务器端线程代码

    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class MyServer {
    
        public static void main(String[] args) throws Exception{
            ServerSocket serverSocket = new ServerSocket(8852);
            System.out.println("Server 等待接收数据~");
            while(true) {
                Socket socket = serverSocket.accept();
           //这里来一个连接请求就让deal去处理,自己在这里等下一个连接请求 deal(socket); } }
    public static void deal(Socket client){
         //这里创建了一个新的线程
    new Thread(new Runnable() { @Override public void run() { DataInputStream dataInputStream=null; DataOutputStream dataOutputStream = null; String receiveFromClient=""; try { dataInputStream = new DataInputStream(client.getInputStream()); dataOutputStream = new DataOutputStream(client.getOutputStream()); //只是这个线程中一直while循环,不影响其他的线程。 while(true) { receiveFromClient = dataInputStream.readUTF(); System.out.println("receive: "+receiveFromClient); if(receiveFromClient.equals("bye")) { dataOutputStream.writeUTF("终于厌倦我了吗?客户端都是大猪蹄子!!"); dataOutputStream.flush(); break; } else { dataOutputStream.writeUTF("你TM给我发 "+receiveFromClient+" 干什么?"); dataOutputStream.flush(); } } }catch (Exception e) { e.printStackTrace(); }finally { try { dataInputStream.close(); dataOutputStream.close(); client.close(); } catch (IOException e) { e.printStackTrace(); } } } }).start(); } }

    客户端代码:

    import java.io.BufferedReader;
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.InputStreamReader;
    import java.net.Socket;
    
    public class MyClient {
        public static void main(String[] args) throws Exception{
            Socket socket = new Socket("127.0.0.1",8852);
            DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
            DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
            BufferedReader bReader = new BufferedReader(new InputStreamReader(System.in));
            String string;
            while(true)
            {
                string=bReader.readLine();
                dataOutputStream.writeUTF(string);
                System.out.println(dataInputStream.readUTF());
                dataOutputStream.flush();
                if(string.equals("bye"))
                    break;
            }
            socket.close();
        }
    }

    结果展示:

    服务器端:

    客户端:

  • 相关阅读:
    web前端的发展态势
    AngularJs 简单入门
    css代码优化篇
    git提交报错:Please make sure you have the correct access rights and the repository exists.
    Activiti工作流框架学习
    遍历map集合的4种方法
    js设置日期、月份增加减少
    Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
    webservice_rest接口_学习笔记
    相互匹配两个list集合+动态匹配${}参数
  • 原文地址:https://www.cnblogs.com/hqinglau/p/10055458.html
Copyright © 2011-2022 走看看