Java进阶(四十七)Socket通信

  今天讲解一个 Hello Word 级别的 Java Socket 通信的例子。具体通讯过程如下:

先启动Server端,进入一个死循环以便一直监听某端口是否有连接请求。然后运行Client端,客户端发出连接请求,服务端监听到这次请求后向客户端发回接收消息,连接建立,启动一个线程去处理这次请求,然后继续死循环监听其他请求。客户端输入字符串后按回车键,向服务器发送数据。服务器读取数据后回复客户端数据。此次请求处理完毕后,启动的线程消亡。如果客户端接收到 “OK”之外的返回数据,会再次发送连接请求并发送数据,服务器会为这次连接再次启动一个线程进行响应。直到当客户端接收到的返回数据为”OK”时,客户端退出。

服务端源代码:

package cn.edu.ujn.socket;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;  

public class Server {
    public static final int PORT = 12345;//监听的端口号

    public static void main(String[] args) {
        System.out.println("服务器启动...\n");
        Server server = new Server();
        server.init();
    }    

    public void init() {
        try {
            ServerSocket serverSocket = new ServerSocket(PORT);
            while (true) {
                // 一旦有堵塞, 则表示服务器与客户端获得了连接
                Socket client = serverSocket.accept();
                // 开启一个新的线程处理这次连接
                new HandlerThread(client);
            }
        } catch (Exception e) {
            System.out.println("服务器异常: " + e.getMessage());
        }
    }

    //  开启一个新的线程处理连接
    private class HandlerThread implements Runnable {
        private Socket socket;
        public HandlerThread(Socket client) {
            socket = client;
            new Thread(this).start();
        }

        public void run() {
            try {
                // 读取客户端数据
                DataInputStream input = new
DataInputStream(socket.getInputStream());
//这里要注意和客户端输出流的写方法对应,否则会抛 EOFException
                String clientInputStr = input.readUTF();
                // 处理客户端数据
                System.out.println("客户端发过来的内容:" + clientInputStr);
                // 向客户端回复信息
                DataOutputStream out = new
                                   DataOutputStream(socket.getOutputStream());
                System.out.print("请输入:\t");
                // 发送键盘输入的一行
                String s = new BufferedReader(new
 InputStreamReader(System.in)).readLine();
                out.writeUTF(s);

                out.close();
                input.close();
            } catch (Exception e) {
                System.out.println("服务器 run 异常: " + e.getMessage());
            } finally {
                if (socket != null) {
                    try {
                        socket.close();
                    } catch (Exception e) {
                        socket = null;
                        System.out.println("服务端 finally 异常:" +
e.getMessage());
                    }
                }
            }
        }
    }
}   

客户端代码

package cn.edu.ujn.socket;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;  

public class Client {
    public static final String IP_ADDR = "localhost";//服务器地址
    public static final int PORT = 12345;//服务器端口号    

    public static void main(String[] args) {
        System.out.println("客户端启动...");
        System.out.println("当接收到服务器端字符为\"OK\"的时候,客户端将终止\n");
        while (true) {
            Socket socket = null;
            try {
                //创建一个流套接字并将其连接到指定主机上的指定端口号
                socket = new Socket(IP_ADDR, PORT); 

                //读取服务器端数据
                DataInputStream input = new
    DataInputStream(socket.getInputStream());
                //向服务器端发送数据
                DataOutputStream out = new
                                  DataOutputStream(socket.getOutputStream());
                System.out.print("请输入: \t");
                String str = new BufferedReader(new
InputStreamReader(System.in)).readLine();
                out.writeUTF(str);    

                String ret = input.readUTF();
                System.out.println("服务器端返回过来的是: " + ret);
                // 如接收到 "OK" 则断开连接
                if ("OK".equals(ret)) {
                    System.out.println("客户端将关闭连接");
                    Thread.sleep(500);
                    break;
                }    

                out.close();
                input.close();
            } catch (Exception e) {
                System.out.println("客户端异常:" + e.getMessage());
            } finally {
                if (socket != null) {
                    try {
                        socket.close();
                    } catch (IOException e) {
                        socket = null;
                        System.out.println("客户端 finally 异常:" +
e.getMessage());
                    }
                }
            }
        }
    }
}
  • 注意: Socket 输出流写数据方法是 writeUTF 时,输入流读取相关数据要用 readUTF。否则会抛 EOFException

    异常。具体原因请参考文后链接。

运行结果



参考资料

http://stackoverflow.com/questions/5489915/java-datainputstream-read-operations-throwing-exceptions





Java进阶(四十七)Socket通信的更多相关文章

  1. Java进阶(四十三)线程与进程的区别

    Java进阶(四十三)线程与进程的区别 1.线程的基本概念   概念:线程是进程中执行运算的最小单位,是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必 ...

  2. 我看不下去鸟。。。。Java和C#的socket通信真的简单吗?

    这几天在博客园上看到好几个写Java和C#的socket通信的帖子.但是都为指出其中关键点. C# socket通信组件有很多,在vs 使用nuget搜索socket组件有很多类似的.本人使用的是自己 ...

  3. Java和C#的socket通信相关(转)

    这几天在博客园上看到好几个写Java和C#的socket通信的帖子.但是都为指出其中关键点. C# socket通信组件有很多,在vs 使用nuget搜索socket组件有很多类似的.本人使用的是自己 ...

  4. java和C#之间SOCKET通信的问题

    转自:http://www.cdtarena.com/javapx/201307/9170.html java和C#之间SOCKET通信的问题 一.服务器端(使用java编写) /** * 监听客户端 ...

  5. Java进阶(四十二)Java中多线程使用匿名内部类的方式进行创建3种方式

    Java中多线程使用匿名内部类的方式进行创建3种方式 package cn.edu.ujn.demo; // 匿名内部类的格式: public class ThreadDemo { public st ...

  6. Java进阶(四十)Java类、变量、方法修饰符讲解

    Java进阶(四十)Java类.变量.方法修饰符讲解 Java类修饰符 abstract: 将一个类声明为抽象类,没有实现的方法,需要子类提供方法实现. final: 将一个类生命为最终(即非继承类) ...

  7. Java进阶(三十七)java 自动装箱与拆箱

    Java进阶(三十七)java 自动装箱与拆箱 前言 这个是jdk1.5以后才引入的新的内容.java语言规范中说道:在许多情况下包装与解包装是由编译器自行完成的(在这种情况下包装称为装箱,解包装称为 ...

  8. Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制

    Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制 JAVA 中原生的 socket 通信机制 摘要:本文属于原创,欢迎转载,转载请保留出处:https://github.co ...

  9. “全栈2019”Java第四十七章:继承与方法

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

随机推荐

  1. ios开发-日期处理(类似朋友圈,微博等的发送时间)

    ios开发中,我们经常要处理从服务器获取的时间.类似朋友圈,微博这些应用.我们经常可以看到“刚刚”,“31分钟前发表”,“昨天5点”,之类的字样. 当时我们从服务器端获取的都是那条朋友圈信息,或者微博 ...

  2. 如何理解java是一个面向对象的语言?(转自Hollis的直面java)

    要想理解这个问题?需要考虑很多 1.什么是面向对象 把问题分解成一个一个步骤,对每个步骤进行相应的抽象,形成对象.通过不同对象之间的调用,组合解决问题,也就是说,在面向对象的编程中,要把属性,行为等封 ...

  3. ●51NOD 1705 七星剑

    题链: http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1705题解: 期望dp,期望的线性性质 (首先对于第k颗星,一定只 ...

  4. 基于vfs实现自己的文件系统

    1.Linux 文件系统组成结构 linux文件系统有两个重要的特点:一个是文件系统抽象出了一个通用文件表示层--虚拟文件系统或称做VFS.另外一个重要特点就是它的文件系统支持动态安装(或说挂载等), ...

  5. hdu 3974 线段树 将树弄到区间上

    Assign the task Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  6. hdu 5478 (数论)

    ⋅n+b1⋅n−k2+1 = 0 (mod C)(n = 1, 2, 3, ...)  (1<=a, b <C) 1.  当n = 1时, a^(k1+b1) + b = 0 ( mod ...

  7. QCA4028软件平台启用双WAN指导

    1 为何要启用双WAN QCA4028的硬件方案,基板上部署了一个LTE模块插槽,同时又外留了一个USB3.0接口,因此,就可以在此硬件平台上调试基于LTE的双WAN,预期实现: A 链路备份,在任意 ...

  8. URI与URL

    为了区分URI与URL,我们要引入URN URI = Universal Resource Identifier 统一资源标志符URL = Universal Resource Locator 统一资 ...

  9. Java内存模型之重排序

    参考链接:https://blog.csdn.net/huzhigenlaohu/article/details/51595676

  10. Python:操作数据库

    (一)      前言 本文说明如何连接Oracle.MySQL.sqlserver,以及执行sql.获取查询结果等. (二)      DB-API      DB-API阐明一系列所需对象和数据库 ...