Java Socket应用

网络基础

  1. 端口号范围0-65535,系统保留0-1023,常见端口http:80,ftp:21,telnet:23
  2. socket=ip+端口
  3. java主要分为InetAdress,URL,Socket(TCP),DatagramSocket(UDP)等类

InetAddress类

InetAddress类没有构造方法,可以通过静态方法获取InetAddress实例对象。

  1. 获取本地主机:getLocalHost()
  2. 通过主机名获取实例:getByName(String Host)
  3. 对实例操作:getHostName()获取主机名,getHostAddress()获取主机ip地址,getAddress()以字节数组的形式返回ip地址

测试:

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;

public class Test{
    public static void main(String[] args) throws UnknownHostException{
        //获取本机名
        InetAddress address=InetAddress.getLocalHost();
        System.out.println(address.getHostName());//输出主机名
        System.out.println(address.getHostAddress());//输出主机ip地址
        byte[] bytes=address.getAddress(); //用字节数组表示ip地址
        System.out.println(Arrays.toString(bytes));
        //通过主机名获取
        InetAddress address2=InetAddress.getByName("你们的大神");//通过名字获取,name可为主机名或者ip地址
        //InetAddress address2=InetAddress.getByName("baidu.com");
        //InetAddress address2=InetAddress.getByName("192.168.0.109");
        System.out.println(address2.getHostName());
        System.out.println(address2.getHostAddress());
        byte[] bytes2=address2.getAddress();
        System.out.println(Arrays.toString(bytes2));
    }
}

URL类

常用构造方法:
  1. URL(String spec)
  2. URL(String protocol, String host, int port,String file)
  3. URL(URL context, String spec) 通过已存在的URL构建
常用get方法:

getRef()获取锚点,getQuery()获取查询字符串,getPort()获取端口号(未指定默认为-1,而浏览器默认为80),其他的见测试用例。

测试:

import java.net.MalformedURLException;
import java.net.URL;

public class Test {
    public static void main(String[] args) throws MalformedURLException {
        URL imooc = new URL("http://www.imooc.com"); // 直接创建
        URL url = new URL(imooc, "/index.html?username=tom#test");// 根据已存在的创建,?表示参数,#表示锚点
        System.out.println(url.getProtocol());
        System.out.println(url.getHost());
        System.out.println(url.getPort()); //如未指定,则返回-1;
        System.out.println(url.getPath());
        System.out.println(url.getFile());
        System.out.println(url.getRef()); //锚点
        System.out.println(url.getQuery()); //查询字符串
    }
}

结果:
http
www.imooc.com
-1
/index.html
/index.html?username=tom
test
username=tom
获取页面内容

使用openStream()获取字节输入流。
测试:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;

//通过URL获取页面内容
public class Test {
    public static void main(String[] args) throws IOException {
        URL url=new URL("http://www.baidu.com");
        InputStream is=url.openStream();//使用openStream获取字节输入流
        InputStreamReader isr=new InputStreamReader(is,"utf-8");//在字节到字符流时需要指定编码方式,避免乱码
        BufferedReader br=new BufferedReader(isr); //添加缓冲流
        
        String data=br.readLine();
        while (data!=null){
            System.out.println(data);
            data=br.readLine();
        }
    }
}

Socket TCP通信

流程

创建ServerSocket和Socket,打开输入输出流,进行操作读写操作,关闭输入输出流,关闭socket。

具体
  1. ServerServer类是服务端socket,侦听客户端的请求。
    常用构造:ServerSocket(int port)
    常用实例方法:accept(),close(),getInetAddress(),getPort()
  2. Socket类是通信的端点。
    常用构造:Socket(InetAddress address,int port)或Socket(String host,int port)
    常用实例方法:getInetAddress(),close()
    getInputStream(),getOutputStream(),shutdownInput(),shutdownOutput()
  3. 多线程服务器,可以接受多个客户端的请求,创建一个线程类,完成对客户端的操作。
测试

Server.java (服务器)

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {

    public static void main(String[] args) throws IOException {
        // 1.创建服务器ServerSocket,绑定端口
        ServerSocket serverSocket = new ServerSocket(8888);
        // 2.使用accept侦听,侦听来自客户端的连接
        System.out.println("****服务器正在启动,侦听连接****");
        int count=0;
        Socket socket;
        while (true) {
            socket = serverSocket.accept();
            ServerThread serverThread = new ServerThread(socket);
            serverThread.start();
            count++;
            System.out.println("client number:"+count);
            InetAddress address=socket.getInetAddress();
            System.out.println("client address:"+address.getHostAddress());
        }
        // serverSocket.close();不会执行到这一步,一直循环,去掉该语句。    
    }
}

ServerThread.java (服务器线程)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;

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 br = null;
        OutputStream os = null;
        PrintWriter pw = null;
        try {
            is = socket.getInputStream();
            isr = new InputStreamReader(is);
            br = new BufferedReader(isr); // 添加缓冲流
            String data = null;
            while ((data = br.readLine()) != null) {
                System.out.println("我是服务端,客户端说:" + data);
            }
            socket.shutdownInput(); // 关闭socket的输入流
            os = socket.getOutputStream();
            pw = new PrintWriter(os);
            pw.write("hello");
            pw.flush();
            socket.shutdownOutput();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (pw != null)
                    pw.close();
                if (os != null)
                    os.close();
                if (br != null)
                    br.close();
                if (isr != null)
                    isr.close();
                if (is != null)
                    is.close();
                if (socket != null)
                    socket.close();
            } catch (IOException e2) {
                // TODO: handle exception
                e2.printStackTrace();
            }

        }

    }
}

Client.java (客户端)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client {
    public static void main(String[] args) throws UnknownHostException, IOException {
        //1.创建客户端socket,指定服务器地址和端口
        Socket socket=new Socket("localhost", 8888);//本地服务器的8888端口
        //2. 获取输出流,发送信息
        OutputStream os=socket.getOutputStream();
        PrintWriter pw=new PrintWriter(os);
        pw.write("admin:456");
        pw.flush();
        socket.shutdownOutput();
        // 3. 获取输入流,接收信息
        InputStream is=socket.getInputStream();
        InputStreamReader isr=new InputStreamReader(is);
        BufferedReader br=new BufferedReader(isr); //添加缓冲流
        String  data=null;
        while((data=br.readLine())!=null){
            System.out.println("我是客户端,服务端说:"+data);
        }
        socket.shutdownInput(); //关闭socket的输入流  
        //3.关闭资源
        is.close();
        isr.close();
        br.close();
        pw.close();
        os.close();
        socket.close();
    }
}

Socket UDP通信

流程

客户端和服务器创建DatagramPacket保存相应数据,创建DatagramSocket,使用DatagramSocket实例的send(),receive()方法来进行通信

具体
  1. DatagramPacket类是UDP用来发送的数据报,UDP无连接,所以数据中可以包含ip地址,端口号等。另外,需要另外定义一个byte[]类型的数组,用来存放数据,这个数组与DatagramPacket实例实质上是同一个。
  2. DatagramSocket类是用来发送或者接受数据报的,主要使用该实例的receive(DatagramPacket packet)和send(DatagramPacket packet)方法,分别把数据存放在packet中的数组中(自己另外定义的),以及相关信息。
  3. 也可以用多线程服务器。
测试

UDPserver.java(UDP服务器)

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class UDPServer {

    public static void main(String[] args) throws IOException {
        // 1. 创建服务器端datagramsocket,指定端口
        DatagramSocket socket = new DatagramSocket(8800);
        // 2. 创建数据报,用于接受客户端发送的数据
        byte[] data = new byte[1024];
        DatagramPacket packet = new DatagramPacket(data, 0, data.length);
        // 3.接受客户端发送的数据,存放在packet
        System.out.println("***服务器正在启动***");
        socket.receive(packet);
        // 4.读取数据
        String info = new String(data, 0, packet.getLength());
        System.out.println("i'm server,client say:" + info);

        // 数据,发送至客户端
        // 1.得到客户端地址,端口,数据
        InetAddress address = packet.getAddress();
        int port = packet.getPort();
        byte[] data2 = "hello".getBytes();
        // 2.创建数据报
        DatagramPacket packet2 = new DatagramPacket(data2, data2.length, address, port);
        // 3.响应客户端
        socket.send(packet2);
        // 4.关闭资源
        socket.close();
    }
}

UDPclient(客户端)

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class UDPClient {
    public static void main(String[] args) throws IOException {
        // 1.定义服务器的地址,端口,数据
        InetAddress address = InetAddress.getByName("localhost");
        int port = 8800;
        byte[] data = "admin:123".getBytes();
        // 2.创建数据报,包含信息
        DatagramPacket packet = new DatagramPacket(data, data.length, address, port);
        // 3.创建DatagramSocket对象
        DatagramSocket socket = new DatagramSocket();
        socket.send(packet);

        // 接受来自服务器数据
        byte[] data2 = new byte[1024];
        DatagramPacket packet2 = new DatagramPacket(data2, 0, data2.length);
        // 3.接受客户端发送的数据,存放在packet
        socket.receive(packet2);
        // 4.读取数据
        String info = new String(data2, 0, packet2.getLength());
        System.out.println("i'm client,server say:" + info);
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,026评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,655评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,726评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,204评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,558评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,731评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,944评论 2 314
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,698评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,438评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,633评论 2 247
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,125评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,444评论 3 255
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,137评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,103评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,888评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,772评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,669评论 2 271

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,102评论 18 139
  • 前言 多年以前自学Java,在本地做了一些笔记。最近几年流行播客,一方面防止丢失,一方面可以帮助其他小伙伴...
    chaohx阅读 963评论 0 3
  • 一、通信前提 两台计算机要进行通信,就要满足以下条件:1.两台主机要有唯一的标识,也就是IP地址,用来表示它们所处...
    不知名的蛋挞阅读 631评论 0 0
  • https://nodejs.org/api/documentation.html 工具模块 Assert 测试 ...
    KeKeMars阅读 6,221评论 0 6
  • 首先这部电影我给一颗星特效,然后,没有了。 特效做得很漂,特别是爱丽丝开着超时空魔球,穿越时间之海层层巨浪回到过去...
    edenvicky阅读 109评论 0 0