java学习笔记#8-Java Socket

网络基础

通信必备条件.png
  • 端口:区别是电脑上的哪个进程发出的通信请求(0 ~ 65535,其中1~1023系统保留)
    http:80 ftp:21 telnet:23
  • 协议:通信过程所使用的语言(TCP/IP)
  • IP地址:互联网中的唯一标识

IP+端口号 组成了Socket。Socket是网络上运行的程序之间双向通信链路的终结点,是TCP和UDP的基础。

JAVA中的网络支持
针对网络通信的不同层次,java提供的网络功能分为四大类

  • InetAddress:用于标识网络上的硬件资源,类IP地址。
  • URL:统一资源定位符 通过URL可以直接读取和写入网络上的数据。
  • Sockets:使用TCP协议实现网络通信的Socket相关的类。
  • Datagram:使用UDP协议,将数据保存在数据报中,通过网络进行通讯。

InetAddress类

无构造方法,无法通过new的方法创造对象。有很多静态方法,可以返回该类。

public void useInetAddress(){

        try {
            //        获取本机的InetAddress
            InetAddress inetAddress = InetAddress.getLocalHost();
            System.out.println("计算机名" + inetAddress.getHostName());
            System.out.println("计算机IP" + inetAddress.getHostAddress());
            System.out.println(inetAddress);

//            其它获取inetAddress的方式
//            InetAddress inetAddress2 = InetAddress.getByName("Edwin");
//            InetAddress inetAddress3 = InetAddress.getByName("1.1.1.10");
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }

    }

URL类

public void useURL(){
        try {
//            创建URL实例
            URL immoc = new URL("http://www.imooc.com");
            URL url = new URL(immoc,"/index.html?username=tom#test");

            System.out.println("协议:"+ url.getProtocol());
            System.out.println("Host:"+ url.getHost());
//            如果为指定端口号,则为-1
            System.out.println("Port:" + url.getPort() );
            System.out.println("filePath:" + url.getPath());
            System.out.println("fileName:" + url.getFile());
            System.out.println("相对路径:"+ url.getRef());
            System.out.println("查询字符串:"+ url.getQuery());




            URL baidu = new URL("http://www.baidu.com");
//            通过URL对象的openStream方法可以获取指定资源的输入流
            InputStream inputStream = baidu.openStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
//            添加缓冲 提高效率
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String data = bufferedReader.readLine();
            while (data!=null){
                System.out.println(data);
                data = bufferedReader.readLine();
            }
            bufferedReader.close();
            inputStreamReader.close();
            inputStream.close();

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

Socket-TCP编程简介

  • 基于TCP协议实现网络通讯的类
    服务端的Socket类
    客户端的ServerSocket类
Socket通信模型.png

实现步骤:
创建serversocket 和socket
打开连接到socket的输入/输出流
按照协议读写
关闭输入输出流

public class ServerModel {
    public static void main(String args[]){
        try {
//       创建服务器端的socket,绑定指定的端口并监听
            ServerSocket serverSocket = new ServerSocket(8888);
//            调用accept监听
            System.out.println("等待客户端链接");
            Socket socket = serverSocket.accept();
//            获取客户端的信息
            InputStream is = socket.getInputStream();
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader bufferedReader = new BufferedReader(isr);
            String info = null;
            while ((info = bufferedReader.readLine())!=null){
                System.out.println("client info : " + info);
            }
            socket.shutdownInput();

            OutputStream outputStream = socket.getOutputStream();
            PrintWriter printWriter = new PrintWriter(outputStream);
            printWriter.write("welcome");
            printWriter.flush();

//           关闭资源
            printWriter.close();
            outputStream.close();

            bufferedReader.close();
            isr.close();
            is.close();
            socket.close();
            serverSocket.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

public class ClientModel {
    public static void main(String args[]){
//        创建客户端的socket,指定服务器端的地址和端口
        try {
            Socket socket = new Socket("localHost",8888);
//            获取输出流发送登陆信息
            OutputStream os = socket.getOutputStream();
            PrintWriter pw = new PrintWriter(os);
            pw.write("userName:edwin;key:123");
            pw.flush();

            socket.shutdownOutput();
//            获取输入流来获取服务器端的响应
            InputStream inputStream = socket.getInputStream();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            String info = null;
            while ((info = bufferedReader.readLine())!= null){
                System.out.println("server said:"+info);
            }
//            关闭资源
            bufferedReader.close();
            inputStream.close();

            pw.close();
            os.close();
            socket.close();

        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


运行结果.png
运行结果.png

为上面所演示的程序添加多线程来实现多客户端的功能
继承线程类

public class ServerThread extends Thread {

    Socket socket = null;
    public ServerThread(Socket socket){
        this.socket = socket;
    }

//    线程执行的操作,响应客户端的请求
    public void run(){
        InputStream is = null;
        InputStreamReader isr = null;
        BufferedReader bufferedReader = null;
        OutputStream outputStream = null;
        PrintWriter printWriter = null;
        try {
 //            获取客户端的信息
            is = socket.getInputStream();
            isr = new InputStreamReader(is);
            bufferedReader = new BufferedReader(isr);
            String info = null;
            while ((info = bufferedReader.readLine())!=null){
                System.out.println("client info : " + info);
            }
            socket.shutdownInput();
            outputStream = socket.getOutputStream();
            printWriter = new PrintWriter(outputStream);
            printWriter.write("welcome");
            printWriter.flush();

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //           关闭资源
            try{
                printWriter.close();
                outputStream.close();
                bufferedReader.close();
                isr.close();
                is.close();
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
}

在服务器端启动循环监听

Socket socket = null;
            int count = 0;
//            循环监听
            while (true){
                socket = serverSocket.accept();
//                创建线程
                ServerThread serverThread = new ServerThread(socket);
                serverThread.run();
                System.out.println(++count);
            }
运行结果.png

Socket-UDP编程简介

UDP无连接无序,数据封装为数据报的形式(datagram)

  • 需要用到的类:
    DatagramPacket:表示数据报包
    DatagramSocket:表示端到端通信的类
public class UDPServer {
    public static void main(String args[]){
        try {
//            创建服务器端的DatagramSocket,指定端口
            DatagramSocket socket = new DatagramSocket(8800);
//            创建数据报文,由于接受服务端的数据
            byte[] data = new byte[1024];
            DatagramPacket packet = new DatagramPacket(data,data.length);
//            接收数据
            System.out.println("服务器端启动...");
            socket.receive(packet);//此方法在接收到数据之前会一直阻塞
//            读取数据
            System.out.println("从客户端得到的数据为:"+ new String(data));
//            向客户端发送响应
//            定义客户端的地址,端口等
            InetAddress address = packet.getAddress();
            int port = packet.getPort();
            byte[] reMessage = "welcome".getBytes();
//            创建数据报
            DatagramPacket rePacket = new DatagramPacket(reMessage,reMessage.length,address,port);
//            响应
            socket.send(rePacket);
            socket.close();
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


public class UDPClient {
    public static void main(String args[]){
        try {
//            定义服务器地址
            InetAddress address =InetAddress.getByName("localHost");
            int port = 8800;
            byte[] data = "此为服务端数据内容".getBytes();
//            创建数据报
            DatagramPacket packet = new DatagramPacket(data,data.length,address,port);
//            创建socket
            DatagramSocket socket = new DatagramSocket();
//            发送
            socket.send(packet);
//            接收响应
            byte[] reMessage = new byte[1024];
            DatagramPacket repacket = new DatagramPacket(reMessage,reMessage.length);
            socket.receive(repacket);
            System.out.println(new String(reMessage));
            socket.close();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
运行结果.png

补充内容

在TCP的示例中使用了多线程来完成持续监听来模拟多个客户端的访问,我们可以通过设计线程的优先级来调整程序的运行情况

...
serverThread.setPriority(4);//范围[1,10],默认:5
...

输出流关闭的过程中会一起关闭socket,所以不单独进行关闭。传输可以以对象的形式进行,只需要使用ObjectOutputStream。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,186评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,858评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,620评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,888评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,009评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,149评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,204评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,956评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,385评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,698评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,863评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,544评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,185评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,899评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,141评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,684评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,750评论 2 351

推荐阅读更多精彩内容