Socket通信

InetAddress 类是java包装用来表示IPd地址的高级表示,InetAddress 不能通过new 方法来获得对象,需要使用类的静态方法来获得一个InetAddress对象

下面就InetAddress所提供的一些类做一个简单的介绍。
1.InetAddress.getByName()
通过主机名获取对应的ip地址:(当然也支持通过IP地址来查找主机名)
该方法会建立与本地DNS的一个连接,来获取名称和地址之间的映射关系。(如果本地DNS缓存了地址,就不再获取连接。)
2**.InetAddress.getLocalHost()**
得到真正的主机名和IP地址。如果获取失败,则会返回一个会送地址,即主机名为“localhost”,以及一个点四分段的ip:‘127.0.0.1’ 。

3**缓存**
由于DNS查找的开销很大,并且如果一个地址不可达,可能会需要几秒钟的时间来确认。InetAddress提供了缓存机制,一旦得到一个给定主机的地址,就会缓存起来,即使重新定义一个InetAddress类,也不会重新再获取一次,而是直接从缓存中获取。但是需要注意一种情况。就是DNS在传输过程中可能的超时。当第一次请求是发生超时失败,而第二次的时候请求已经到达,并缓存了起来。所有Java在缓存不可达的地址时,只缓存了10s。
4.安全性问题
从主机名创建一个InetAddress对象,被认为是一种不安全的操作。因为这需要一个DNS查找,在默认的安全管理控制器下的不可行applet只允许获取它本机的主机地址以及ip。不允许不可行代码由任何其他主机名创建InetAddress对象。不可信的代码不允许对第三方主机完成任意查找。
5.获取方法
public String getHostName()

publlic String getCanonicalHostName()

public byte[] getAddress()

public String getHostAddress()
没有对应的setHostName()以及getHostName()。代表着无法通过反射来改变其内部的。因此是线程安全的。
6.地址类型
ip地址分为不同的类型,例如:‘’127.0.0.1‘’属于本地回送地址。Java提供了10中方法来判断一个ip地址属于那种不同的分段。

public boolean isAnyLocalAddress()


URL 统一资源定位符,

创建方法:

//创建URL实例

            URL imooc = new URL("http://www.baidu.com");

可以将URL包装成一个新的URL对象

//?后面表示参数#后面表示锚点

            URL url = new URL(imooc, "/index.html?username=tom#test");

创建URL并访问资源的代码如下:

package xxlong.test;
import java.io.BufferedReader;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.io.InputStream;
import java.io.InputStreamReader;
public class URLTest {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        try {
            //创建URL实例
            URL imooc = new URL("http://www.baidu.com");
            InputStream is = imooc.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();
            }
            br.close();
            isr.close();
            is.close();
            /*
            //?后面表示参数#后面表示锚点
            URL url = new URL(imooc, "/index.html?username=tom#test");
            System.out.println("协议:" + url.getProtocol());
            System.out.println("文件路径: " + url.getPath());
            //如果没有设置端口号,则使用默认端口号,方法返回-1
            System.out.println("端口: " + url.getPort());
            System.out.println("主机: " + url.getHost());
            System.out.println("文件名:" + url.getFile());
            System.out.println("相对路径:" + url.getRef());
            System.out.println("查询字符串:" + url.getQuery());
            System.out.println("" + url.getAuthority());
            System.out.println(" " + url.getContent());
            */
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }

}

Socket

网络上的两个程序通过一个双向的通信连接实现的数据交换,这个连接的一段称为一个socket,

TCP协议:transmission control protocol,传输控制协议,是一种面向连接的、可靠地、基于字节流的传输层通信协议

使用socket进行tcp通信时,首先需要创建一个服务器端,然后创建一个客户端,然后进行连接,创建ServerSocket的步骤:

1,创建ServerSocket对象,一般需要指定端口号

ServerSocket serverSocket = new ServerSocket(8889);

2,调用accept方法开启监听

socket = serverSocket.accept();

3,通过socket的getgetInputStream()方法获取输入流,读取客户端信息

            is = socket.getInputStream();

            //包装成字符流,以提高读取的效率

            isr = new InputStreamReader(is);
            br = new BufferedReader(isr);
            //4.读取信息
            info = br.readLine();
            while(info != null) {
                System.out.println(info);
                info = br.readLine();

            }

4,关闭socket 及相关资源

            socket.shutdownInput();

5,响应客户端

            os = socket.getOutputStream();
            pw = new PrintWriter(os);
            pw.write("欢迎咯!");
            pw.flush();

            socket.shutdownOutput();

6,关闭其他资源,必须关闭,因此放到finally语句中

finally {
            //6.关闭其他资源
            
            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();
            }

ServerSocket完整代码如下

package xxlong.tet;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetAddress;
public class Server {
    public static void main(String[] args) {
        try {
            //1.创建ServerSocket
            ServerSocket serverSocket = new ServerSocket(8889);
            System.out.println("服务器已开启监听");
            Socket socket = null;
            int count = 0;
            //2.开启监听
            while(true) {
                socket = serverSocket.accept();
                ServerThread st = new ServerThread(socket);
                st.start();
                count++;
                System.out.println("当前客户端数量:" + count);
                InetAddress ia = socket.getInetAddress();
                System.out.println("IP: " + ia.getHostAddress());
            }
            
            
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

服务器线程:

package xxlong.tet;
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;
    }
    //多线程处理Socket通信
    public void run() {
        InputStream is = null;
        InputStreamReader isr = null;
        BufferedReader br = null;
        String info = null;
        OutputStream os = null;
        PrintWriter pw = null;
        try {
            is = socket.getInputStream();
            isr = new InputStreamReader(is);
            br = new BufferedReader(isr);
            //4.读取信息
            info = br.readLine();
            while(info != null) {
                System.out.println(info);
                info = br.readLine();
            }
            //5.关闭Socket输入流
            socket.shutdownInput();
            os = socket.getOutputStream();
            pw = new PrintWriter(os);
            pw.write("欢迎咯!");
            pw.flush();
            socket.shutdownOutput();
            
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            //6.关闭其他资源
            
            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 e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
    }
    
    
}

客户端

1,客户端创建socket

Socket socket = new Socket("localhost", 8889);

指定地址及端口号

2,获得字节输出流,向服务器发送信息

OutputStream os = socket.getOutputStream();
            PrintWriter pw = new PrintWriter(os);
            pw.write("用户名:user2;密码:123456");
            pw.flush();

            socket.shutdownOutput();

3,读取服务器端响应

InputStream is = socket.getInputStream();
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            String info = br.readLine();
            while(info != null) {
                System.out.println(info);
                info = br.readLine();

            }

4,关闭资源

br.close();
            isr.close();
            is.close();
            pw.close();
            os.close();

            socket.close();

UDP通信

UDP:user datagram protocol 用户数据报协议,是一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。

UDP通信服务器端

package xxlong.test;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.net.InetAddress;
public class Server {
    public static void main(String[] args) {
        try {
            //创建DatagramSocket
            DatagramSocket socket = new DatagramSocket(8888);
            //缓存数据数组
            byte[] data = new byte[1024];
            //创建DatagramPacket
            DatagramPacket packet = new DatagramPacket(data, data.length);
            System.out.println("服务器已经启动");
            //接受客户端信息
            socket.receive(packet);//此方法接收到数据报之前会一直阻塞
            String info = new String(packet.getData(), 0, packet.getLength());
            System.out.println("服务端接收到信息:" + info);
            InetAddress address = packet.getAddress();
            int port = packet.getPort();
            //响应客户端
            byte[] datato = "欢迎使用".getBytes();
            DatagramPacket packet2 = new DatagramPacket(datato, datato.length, address, port);
            socket.send(packet2);
            System.out.println("已响应");
            //关闭socket
            socket.close();
            
            
            
        } catch (SocketException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

客户端

package xxlong.test;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.net.DatagramSocket;
public class Client {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        try {
            //获取IP
            InetAddress address = InetAddress.getByName("localhost");
            //指定端口号
            int port = 8888;
            //要发送信息
            byte[] data = "用户名:user;密码:123456".getBytes();
            //创建数据报并指定发送地址及端口号
            DatagramPacket packet = new DatagramPacket(data, data.length, address, port);
            //创建DatagramSocket
            DatagramSocket socket = new DatagramSocket();
            //发送数据报
            socket.send(packet);
            //准备接收数据报
            byte[] data2 = new byte[1024];
            DatagramPacket packet2 = new DatagramPacket(data2, data2.length);
            //等待系统响应
            socket.receive(packet2);
            System.out.println("已接收响应");
            String reply = new String(data2, 0, packet2.getLength());
            System.out.println("服务器说: " + reply);
            //关闭socket
            socket.close();
            
            
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SocketException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }

}











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值