网络通讯编程

概述

  • Java.net实现Java的网络功能

InetAddress

  • 获取本地主机名+IP地址
InetAddress ia1 = InetAddress.getLocalHost();
  • 根据名称获取IP地址
InetAddress[] ia2 = InetAddress.getAllByName("www.baidu.com")

Socket(套接字)

  • 客户端
  • Socket用于创建套接字对象
  • 构造方法
Socket()
Socket(InetAddress addr,int port)
Socket(String hostName,int port)
	hostName ->"www.baidu.com"
			 ->"183.232.231.172"
  • 方法
getRemoteSocketAddress()

ServerSocket

  • 服务器端
  • 构造方法
ServerSocket(port)
  • 方法
getInetAddress():IP地址
getLocalPort():端口号
accept():阻塞式(等到客户端连接才继续)获取客户端套接字,返回Socket
	客户端port与服务端port相同可以相连接,获取到套接字

Server+Client

需求1

  • 服务器传送时间到客户端
  • ServerSocket
public class t3_Server {
    public static void main(String[] args) throws IOException {
        final int port = 10000;
        //绑定10000的端口
        ServerSocket ss = new ServerSocket(port);
	
		System.out.println(ss.getInetAddress() + "启动,监听" + ss.getLocalPort() + "端口");

        Date d = null;
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String time = null;

		//死循环:多个客户端连接同一服务器
        while (true) {
            //获得客户端套接字
            Socket s = ss.accept();
            System.out.println("获得客户端:" + s.getRemoteSocketAddress() + "的联接");
           
            d = new Date();
            time = df.format(d);

            //套接字编程的底层是IO,使用输出流(相对当前程序看)
            try (OutputStream os = s.getOutputStream();) {
                os.write(time.getBytes());
                os.flush();
            } catch (Exception e) {
                e.printStackTrace();
            }

            System.out.println("服务端断开与客户端的连接");
            s.close();
        }
    }
}
  • Socket
public class t3_Client {
    public static void main(String[] args) throws IOException {
        Socket s = new Socket("localhost", 10000);
		System.out.println("联接成功  " + s);
		
        //使用输入流接收服务端数据
        try (InputStream in = s.getInputStream()) {
            byte[] b = new byte[1024];
            int length = -1;
            //客户端等待服务端的响应,阻塞式
            while ((length = in.read(b, 0, b.length)) != -1) {
                String str = new String(b, 0, length);
                System.out.println("服务端的响应:" + str);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println("客户端断开与服务端的连接");
        s.close();
    }
}

需求2

  • 服务器启动时自动选一个空闲端口
  • 确定传输的是字节流,将其转成字符流以提升性能
  • ServerSocket
public class t4_Server {
    public static void main(String[] args) throws IOException {
        //需求1.自动选一个端口
        final int port = 10000;//端口固定   会存在端口占用问题
        ServerSocket ss = null;
        for (int i = 10000; i < 65535; i++) {//10000以下端口尽量不要占
            try {
                ss = new ServerSocket(i);//绑定i的端口
                break;//注意:端口绑定成功打断循环
            } catch (Exception e) {
                if (e instanceof BindException) {
                    System.out.println("端口:" + i + "已占用");
                }
            }
        }

        System.out.println(ss.getInetAddress() + "启动,监听" + ss.getLocalPort() + "端口");

        Date d = null;
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String time = null;

        while (true) {
        	//获得客户端套接字
            Socket s = ss.accept();
            System.out.println("获得客户端:" + s.getRemoteSocketAddress() + "的联接");
            d = new Date();
            time = df.format(d);

            //需求2:将字节流转成字符流以提升性能
            try (OutputStreamWriter os = new OutputStreamWriter(s.getOutputStream());) {
                os.write(time);
                os.flush();
            } catch (Exception e) {
                e.printStackTrace();
            }

            System.out.println("服务端断开与客户端的连接");
            s.close();
        }
    }
}
  • Socket
public class t4_Client {
    public static void main(String[] args) throws IOException {
        Socket s = new Socket("localhost", 10000);
        System.out.println("联接成功  " + s);

        //需求2:将字节流转成字符流以提升性能
        try (InputStreamReader in = new InputStreamReader(s.getInputStream())) {
            char[] b = new char[1024];
            int length = -1;
            
            while ((length = in.read(b, 0, b.length)) != -1) {
                String str = new String(b, 0, length);
                System.out.println("服务端的响应:" + str);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println("客户端断开与服务端的连接");
        s.close();
    }
}

需求3

  • 一个服务器与一个客户端的聊天
  • 要求客户端先发
  • ServerSocket
public class t5_talkServer {
    public static void main(String[] args) {
        ServerSocket ss = null;
        for (int i = 10000; i < 65535; i++) {
            try {
                ss = new ServerSocket(i);
                break;
            } catch (Exception e) {
                if (e instanceof BindException) {
                    System.out.println("端口:" + i + "被占用");
                }
            }
        }
        System.out.println("启动:" + ss.getInetAddress().getHostAddress() + ",监听:" + ss.getLocalPort());

        //通过键盘录入聊天消息
        Scanner sc = new Scanner(System.in);
        while (true) {
            try (Socket s = ss.accept();
                 Scanner sn = new Scanner(s.getInputStream());
                 PrintWriter pw = new PrintWriter(s.getOutputStream())
            ) {
                System.out.println("客户端:" + s.getRemoteSocketAddress() + "连上");

                do {
                    String response = sn.nextLine();
                    System.out.println("客户端:" + s.getRemoteSocketAddress() + "对server说:" + response);
                    
                    if ("bye".equalsIgnoreCase(response)) {
                        System.out.println("服务器主动断开与客户端的连接");
                        break;
                    }

                    System.out.println("输入服务器对客户端" + s.getRemoteSocketAddress() + "说:");
	                String line = sc.nextLine();
	                pw.println(line);
	                pw.flush();
	                
                    if ("bye".equalsIgnoreCase(line)) {
                        System.out.println("客户端主动断开与服务器的连接");
                        break;
                    }
                } while (true);
                System.out.println("服务器与客户端" + s.getRemoteSocketAddress() + "主动结束聊天");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
  • Socket
public class t5_talkClient {
    public static void main(String[] args) throws IOException {
        Socket s = new Socket("121.43.226.171", 10000);
        System.out.println("联接成功  " + s);

        try (Scanner sc = new Scanner(System.in);//键盘录入C话
             Scanner sn = new Scanner(s.getInputStream());//获取服务器的回答
             PrintWriter pw = new PrintWriter(s.getOutputStream());//客户端的回答
        ) {
            do {
                System.out.println("客户端对服务器端说:");
                String line = sc.nextLine();
                pw.println(line);
                pw.flush();

                if ("bye".equalsIgnoreCase(line)) {
                    System.out.println("客户端主动断开与服务器的连接");
                    break;
                }

                String response = sn.nextLine();
                System.out.println("服务器对客户端说:" + response);

                if ("bye".equalsIgnoreCase(line)) {
                    System.out.println("服务器主动断开与客户端的连接");
                    break;
                }

            } while (true);
            System.out.println("在服务器正常结束聊天");
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println("客户端关闭");
        s.close();
    }
}

需求4

  • 一个服务器与n个客户端聊天
  • 引入线程:聊天是耗时操作
  • ServerSocket
public class t6_talkServer_duo {
    public static void main(String[] args) {
        ServerSocket ss = null;
        for (int i = 10000; i < 65535; i++) {
            try {
                ss = new ServerSocket(i);
                break;
            } catch (Exception e) {
                if (e instanceof BindException) {
                    System.out.println("端口:" + i + "被占用");
                }
            }
        }
        System.out.println("启动:" + ss.getInetAddress().getHostAddress() + ",监听:" + ss.getLocalPort());

        Scanner sc = new Scanner(System.in);
        while (true) {
            try {
                Socket s = ss.accept();//不能写在try()中,否则套接字将被关闭
                System.out.println("客户端:" + s.getRemoteSocketAddress() + "连上");

                TalkTask tt = new TalkTask(s);
                Thread t = new Thread(tt);
                t.start();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

class TalkTask implements Runnable {
    //套接字
    private Socket s;
    Scanner sc = new Scanner(System.in);
    public TalkTask(Socket s) {this.s = s;}

    @Override
    public void run() {
        try {
            Socket s = this.s;
            Scanner sn = new Scanner(s.getInputStream());
            PrintWriter pw = new PrintWriter(s.getOutputStream());

            do {
                String response = sn.nextLine();
                System.out.println("客户端:" + s.getRemoteSocketAddress() + "对server说:" + response);
                
                if ("bye".equalsIgnoreCase(response)) {
                    System.out.println("服务器主动断开与客户端的连接");
                    break;
                }

                System.out.println("输入服务器对客户端" + s.getRemoteSocketAddress() + "说:");
                String line = sc.nextLine();
                pw.println(line);
                pw.flush();

                if ("bye".equalsIgnoreCase(line)) {
                    System.out.println("客户端主动断开与服务器的连接");
                    break;
                }
            } while (true);
            System.out.println("服务器与客户端" + s.getRemoteSocketAddress() + "主动结束聊天");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

编写应用层协议连接百度

1.手工编写

public class t7_telent_baidu {
    public static void main(String[] args) {
        String website = "www.baidu.com";
        int port = 80;

        //应用层协议
        String http = "GET / HTTP/1.0\r\nHost: www.baidu.com\r\n\r\n";
        try (Socket s = new Socket(website, port);
             OutputStream out = s.getOutputStream();
             InputStream in = s.getInputStream();
        ) {
            //将协议写到服务端
            out.write(http.getBytes());
            out.flush();

			//获取服务端的响应
            byte[] bytes = new byte[10 * 1024];
            int length = -1;
            while ((length = in.read(bytes, 0, bytes.length)) != -1) {
                String str = new String(bytes, 0, length);
                System.out.println(str);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2.URL类

  • 统一资源定位符
//1.string:协议+访问的主机地址
URL url = new URL("http://www.baidu.com");
//2.打开连接
URLConnection con = url.openConnection();
//3.获取响应信息getXXXX()
String contentType = con.getContentType();
long conLength = con.getContentLength();

//获取流
InputStream in = con.getInputStream();
byte[] bytes = new byte[10 * 1024];
int length = -1;
while ((length = in.read(bytes, 0, bytes.length)) != -1) {
    String str = new String(bytes, 0, length);
    System.out.println(str);
}

3.HttpURLConnection类

//1.string:协议+访问的主机地址
URL url = new URL("http://www.hyycinfo.com/");
//2.打开连接
HttpURLConnection con = (HttpURLConnection) url.openConnection();
//3.设置请求头
con.setRequestProperty("HOST", "www.hyycinfo.com");
//4.打开输入输出流
con.setDoInput(true);
con.setDoOutput(true);
//5.获取响应信息getXXXX()
String contentType = con.getContentType();
long conLength = con.getContentLengthLong();
System.out.println(contentType + "\t" + conLength);

//获取流
InputStream in = con.getInputStream();
byte[] bytes = new byte[10 * 1024];
int length = -1;
while ((length = in.read(bytes, 0, bytes.length)) != -1) {
    String str = new String(bytes, 0, length);
    System.out.println(str);
}

4.UDP

  • UDP中的每个包都要有明确接收地址
  • 不安全的协议(不管服务器开不开都发)
  • 没有客户端与服务器的概念,只能说发送端与接收端
  • 构造方法
DatagramPacket dp = new DatagramPacket(字节类型数据,数据长度,new InetSocketAddress(接收方地址,接收方端口号))
DatagramSocket ds = new DatagramSocket(本机端口号);
  • 发送端+接收端
1.send()——发送端
	String s = "helloworld";
	DatagramPacket dp = new DatagramPacket(s.getBytes(), s.getBytes().length, new InetSocketAddress("127.0.0.1", 3333));
	DatagramSocket ds = new DatagramSocket(15678);
	ds.send(dp);
	ds.close();
	System.out.println("发送成功");
2.receive()——接收端
	byte buf[] = new byte[1024];
	DatagramPacket dp = new DatagramPacket(buf, buf.length);
	//占用UDP的3333端口接收,端口号要对应
	DatagramSocket ds = new DatagramSocket(3333);
	while (true) {
	    //3333端口接受数据,数据存于dp数据包buf缓存空间
	    ds.receive(dp);//阻塞式
	    System.out.println(new String(buf, 0, dp.getLength()));
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值