Java网络编程
来源:互联网 发布:b站直播间刷人气源码 编辑:程序博客网 时间:2024/06/05 23:49
一、InetAddress
InetAddress类来代表IP地址,2个子类:Inet4Address, Inet6Address,它们分别代表IPv4地址和IPv6地址。
InetAddress类没有构造器,而是提供了两个静态方法来获取InetAddress实例:
1、getByName(String host):根据主机获取对应的InetAddress对象。
2、getByAddress(byte口addr):根据原始IP地址来获取。
InetAddress还提供了如下三个方法来获取InetAddress实例对应的IP地址和主机名:
1)String getCanonicalHostName():获取此IP地址的全限定域名。
2)String getHostAddress():返回该InetAddress实例对应的IP地址字符串(以字符串形式)。
3)String getHostName():获取此IP地址的主机名。
除此之外,InetAddress类还提供了一个getLocalHost()方法来获取本机IP地址对应的InetAddress实例。isReachable()方法,用于测试是否可以到达该地址。
public class Test01{ public static void main(String[] args) throws UnknownHostException{ System.out.println("--------根据本地主机获取InetAddress实例-----------"); //获取本机的InetAddress实例 InetAddress address1 = InetAddress.getLocalHost(); //直接输出InetAddress对象 System.out.println(address1); //输出结果 System.out.println("计算机名称:"+address1.getHostName()); System.out.println("IP地址:"+address1.getHostAddress()); //获取字节数组形式的IP地址 byte[] bytes = address1.getAddress(); System.out.println("字节数组形式的IP地址:"+Arrays.toString(bytes)); System.out.println("--------根据主机名获取InetAddress实例-----------"); //根据主机名获取InetAddress实例 InetAddress address2 = InetAddress.getByName("HTACLW0UOMUIZKE"); //直接输出InetAddress对象 System.out.println(address2); System.out.println("计算机名称:"+address2.getHostName()); System.out.println("IP地址:"+address2.getHostAddress()); System.out.println("--------根据IP地址获取InetAddress实例-----------"); //根据IP地址获取InetAddress实例 InetAddress address3 = InetAddress.getByName("192.168.0.109"); //直接输出InetAddress对象 System.out.println(address3); System.out.println("计算机名称:"+address3.getHostName()); System.out.println("IP地址:"+address3.getHostAddress()); }}
二、ServerSocket、Socket
TCP/IP是一种可靠的网络协议,它在通信的两端各建立一个Socket,形成网络虚拟链路。Java对基于TCP协议的网络通信提供了良好的封装,Java使用Socket对象来代表两端的通信端口,并通过Socket产生IO流进行网络通信。
使用ServerSocket创建TCP服务器端.
(1)
Java中能接收其他连接请求的类是ServerSocket,ServerSocket对象用于监听来自客户端的Socket连接,如果没有连接,它将一直处于等待状态。ServerSocket包含一个监听来自客户端请求的方法。
Socket accept()接到请求,返回与客户端Socket对应的Socket(每个TCP连接有两个Socket)否则该方法将一直处于等待状态,线程也被阻塞。
ServerSocket构造器
ServerSocket(int port):用指定的端口port来创建一个ServerSocket。该端口应该有一个有效的端口数值,即0~65535。
ServerSoccket(int port,int backlog)
ServerSocket(int port,int backlog,InetAddress localAddr)
(2)使用Socket进行通信
客户端使用Socket的构造器来连接到指定服务器,Socket构造器。
Socket(InetAddress/String remoteAddress,int port)创建连接到指定远程主机、端口的Socket,没指定本地地址、本地端口,默认使用本地主机的默认IP地址,默认使用系统动态分配的端口
Socket(InetAddress/String remoteAddress,int port,InetAddress localAddr,int localPort)指定本地IP地址和本地端口,适用于本地主机有多个IP地址的情形
当客户端、服务器端产生了对应的Socket之后,程序无须再区分服务器端、客户端,而是通过各自的Socket进行通信。Socket提供了两个方法来获取输入流和输出流。
InputStream getInputStream()
返回该Socket对象对应的输入流
OutputStream getOutputStream()
返回该Socket对象对应的输出流出数据
三、例子
(1)TCP(单线程)
public class Server { public static void main(String[] args) throws IOException{ //创建一个ServerSocket,用于监听客户端Socket的连接请求 ServerSocket ss = new ServerSocket(30000); //采用循环换不断地接收来自客户端的请求 while (true){ //每当接收到客户端Socket的请求时,服务器端也对应产生一个Socket Socket s = ss.accept(); //将Socket对应的输出流包装成PrintStream PrintStream ps = new PrintStream(s.getOutputStream()); //进行普通的IO操作 ps.println("您好,您收到了服务器的问候!"); //关闭输出流,关闭Socket ps.close(); s.close(); } }} ****************************************public class Client { public static void main(String[] args) throws IOException{ Socket socket = new Socket("127.0.0.1", 30000); //将Socket对应的输入流包装成BufferedReader BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); //进行普通IO操作 String line = br.readLine(); System.out.println("来自服务器的数据:" + line); //关闭输入流,关闭Socket br.close(); socket.close(); }}
(2)多线程
命令行界面的C/S聊天室应用,服务器端应该包含多个线程,每个Socket对应一个线程,该线程负责读取Socket对应输入流的数据(从客户端发送过来的数据),并将读到的数据向每个Socket输出流发送一次(将一个客户端发送的数据“广播”给其他客户端),因此需要在服务器端使用List来保存Socket。
首先是服务器端的实现代码,一共有两个类,一个是创建ServerSocket监听的主类,一个是负责处理每个Socket通信的线程类。
监听主类:
public class MyServer { //定义保存所有Socket的ArrayList,并将其包装为线层安全的 public static List<Socket> socketList = Collections.synchronizedList(new ArrayList<>()); public static void main(String[] args) throws IOException{ ServerSocket ss = new ServerSocket(30001); while (true){ //此行代码会阻塞,将一直等待别人的连接 Socket s = ss.accept(); socketList.add(s); //每当客户端连接后启动一个ServerThread线程为该客户端服务 new Thread(new ServerThread(s)).start(); } }}
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
服务器端只负责接收客户端Socket的连接请求,每当客户端Socket连接到该ServerSocket之后,程序将对应Socket加入socketList集合中保存,并为该Socket启动一个线程,该线程负责处理该Socket所有的通信任务。
负责处理Socket通信的线程类:
public class ServerThread implements Runnable{ //定义当前线程所处理的Socket Socket s = null; //该线程所处理的Socket对应的输入流 BufferedReader br = null; public ServerThread(Socket s) throws IOException{ this.s = s; //初始化该Socket对应的输入流 br = new BufferedReader(new InputStreamReader(s.getInputStream())); } public void run(){ try{ String content = null; //采用循环不断地从Socket中读取客户端发送过来的数据 while ((content = readFromClient()) != null){ //遍历socketList中的每个socket //将读到的内容向每个Socket发送一次 for(Socket s : MyServer.socketList){ PrintStream ps = new PrintStream(s.getOutputStream()); ps.println(content); } } }catch (IOException e){ e.printStackTrace(); } } //定义读取客户端数据的方法 private String readFromClient(){ try{ return br.readLine(); } //如果捕获异常,则表明该Socket对应的客户端已经关闭 catch (IOException e){ //删除该Socket MyServer.socketList.remove(s); } return null; }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
每个客户端包含两个线程,一个负责读取用户的键盘输入,并将用户输入的数据写入Socket对应的输出流中;一个负责读取Socket对应输入流中的数据(从服务端发送过来的数据),并将这些数据打印输出。其中负责读取用户键盘输入的线程由MyClient负责,也就是有程序的线程负责。
客户端主程序:
public class MyClient { public static void main(String[] args) throws Exception{ Socket s = new Socket("127.0.0.1", 30001); //客户端启动ClientThread线程不断地读取来自服务器的数据 new Thread(new ClientThread(s)).start(); //获取该Socket对应的输出流 PrintStream ps = new PrintStream(s.getOutputStream()); String line = null; //不断地读取键盘输入 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); while ((line = br.readLine()) != null){ //将用户的键盘输入内容写入Socket对应的输出流 ps.println(line); } }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
客户端线程:
public class ClientThread implements Runnable{ //该线程负责处理的Socket private Socket s; //该线程所处理的Socket对应的输入流 BufferedReader br = null; public ClientThread(Socket s) throws IOException{ this.s = s; br = new BufferedReader(new InputStreamReader(s.getInputStream())); } public void run(){ try{ String content = null; //不断地读取Socket输入流中的内容,并将这些内容打印输出 while ((content = br.readLine()) != null){ System.out.println(content); } }catch (Exception e){ e.printStackTrace(); } }}
- 【网络编程】JAVA网络编程
- java网络编程:网络基本概念
- Java网络编程-UDP编程
- Java 高层网络编程
- Java网络编程2
- Java网络编程3
- Java网络编程4
- Java网络服务器编程
- java网络编程1
- java网络编程2
- JAVA网络编程
- Java网络服务器编程
- java网络编程
- Java 高层网络编程
- Java 高层网络编程
- Java网络服务器编程
- Java网络编程
- JAVA网络编程
- redis数据库
- Struts2文件上传
- maven项目的建立中出错
- mysql 中 时间和日期函数
- JavaScript:理解事件、事件处理函数、钩子函数、回调函数
- Java网络编程
- Hadoop Yarn 框架原理及运作机制
- 关于设计模式心得
- 九度OJ 1002 Grading
- eclipse或myeclipse复制项目后,启动项目,访问的还是原来的项目
- scrapy爬虫小例子
- Idea的基本使用(开发实用)
- Cygwin安装与使用入门
- 修改github远程仓库名称