zoukankan      html  css  js  c++  java
  • Java Socket

    重要的Socket API:

     java.net.Socket继承于java.lang.Object,有八个构造器,其方法并不多,下面介绍使用最频繁的三个方法,

      . Accept方法用于产生”阻塞”,直到接受到一个连接,并且返回一个客户端的Socket对象实例。”阻塞”是一个术语,它使程序运行暂时”停留”在这个地方,直到一个会话产生,然后程序继续;通常”阻塞”是由循环产生的。

      . getInputStream方法获得网络连接输入,同时返回一个InputStream对象实例。 
      . getOutputStream方法连接的另一端将得到输入,同时返回一个OutputStream对象实例。

      注意:其中getInputStream和getOutputStream方法均会产生一个IOException,它必须被捕获,因为它们返回的流对象,通常都会被另一个流对象使用。

          JAVA API1.6 中文.CHM

    InetAddress:

     1 import java.net.Inet4Address;
     2 import java.net.UnknownHostException;
     3 import java.util.Arrays;
     4 
     5 public class InetAddress {
     6 
     7     public static void main(String[] args) throws UnknownHostException{
     8         // 获取本机的InetAddress实例
     9         Inet4Address address=(Inet4Address) Inet4Address.getLocalHost();
    10         System.out.println("计算名:"+address.getHostName());
    11         System.out.println("IP地址:"+address.getHostAddress());
    12         byte[] bytes=address.getAddress();//获取字节数组形式的IP地址
    13         System.out.println("字节数组形式的IP:"+Arrays.toString(bytes));
    14         System.out.println("直接输出InetAdress对象:"+address);//直接输出InetAdress对象
    15         
    16         //根据机器名获取InetAdress实例
    17         Inet4Address address2=(Inet4Address) Inet4Address.getByName("DESKTOP-8J7SNCN");
    18         System.out.println("计算名:"+address2.getHostName());
    19         System.out.println("IP地址:"+address2.getHostAddress());
    20         
    21         
    22         //根据IP地址获取InetAdress实例
    23         Inet4Address address3=(Inet4Address) Inet4Address.getByName("169.254.38.168");
    24         System.out.println("计算名:"+address3.getHostName());
    25         System.out.println("IP地址:"+address3.getHostAddress());
    26         
    27     }
    28 
    29 }

    url:

     1 import java.net.MalformedURLException;
     2 import java.net.URL;
     3 
     4 public class Url {
     5     public static void main(String[] args) {
     6         try{
     7             //创建一个URL实例
     8             URL imooc=new URL("http://www.imooc.com");
     9             //?后面表示参数,#后面表示锚点
    10             URL url = new URL(imooc,"/index.html?username=tom#test");
    11             System.out.println("协议 :"+ url.getProtocol());
    12             System.out.println("主机 :"+ url.getHost());
    13             //如果未指定端口号,则使用协议默认端口号
    14             System.out.println("端口号 :"+ url.getPort());
    15             System.out.println("文件路径 :"+ url.getPath());
    16             System.out.println("文件名称 :"+ url.getFile());
    17             System.out.println("相对路径 :"+ url.getRef());
    18             System.out.println("查询字符串:"+ url.getQuery());
    19         }catch(MalformedURLException e){
    20             e.printStackTrace();
    21         }
    22 
    23     }
    24 
    25 }
     1 import java.io.BufferedReader;
     2 import java.io.IOException;
     3 import java.io.InputStream;
     4 import java.io.InputStreamReader;
     5 import java.net.MalformedURLException;
     6 import java.net.URL;
     7 
     8 
     9 /*
    10  * 使用URL读取网页内容
    11  */
    12 public class Url2 {
    13     public static void main(String[] args) {        
    14         try {
    15             //创建URL实例
    16             URL url=new URL("http://www.baidu.com");
    17             //通过URL的openStream方法获取URL对象所表示的资源的字节输入流
    18             InputStream is=url.openStream();
    19             //将字节输入流转换为字符输入流
    20             InputStreamReader isr=new InputStreamReader(is,"utf-8");
    21             //为字节输入流添加缓冲
    22             BufferedReader br=new BufferedReader(isr);
    23             String data=br.readLine();
    24             while(data!=null){
    25                 System.out.println(data);
    26                 data=br.readLine();
    27             }
    28             br.close();
    29             isr.close();
    30             is.close();
    31         } catch (MalformedURLException e) {
    32             e.printStackTrace();
    33         } catch (IOException e) {
    34             e.printStackTrace();
    35         }
    36     }
    37 
    38 }

    重点!!!

    通过 Socket 实现 TCP 编程

    构造ServerSocket

    构造方法:

      ServerSocket() ~创建非绑定服务器套接字。

      ServerSocket(int port) ~创建绑定到特定端口的服务器套接字。

      ServerSocket(int port, int backlog) ~利用指定的 backlog 创建服务器套接字并将其绑定到指定的本地端口号。

      ServerSocket(int port, int backlog, InetAddress bindAddr) ~使用指定的端口、侦听 backlog 和要绑定到的本地 IP 地址创建服务器。

    1.1 绑定端口

    除了第一个不带参数的构造方法以外, 其他构造方法都会使服务器与特定端口绑定, 该端口有参数 port 指定. 例如, 以下代码创建了一个与 80 端口绑定的服务器:

    1 ServerSocket serverSocket = new ServerSocket(80);  

    1.2 设定客户连接请求队列的长度

    当服务器进程运行时, 可能会同时监听到多个客户的连接请求. 例如, 每当一个客户进程执行以下代码:

    1 Socket socket = new Socket("www.javathinker.org", 80); 

    就意味着在远程 www.javathinker.org 主机的 80 端口上, 监听到了一个客户的连接请求.

    例子:

    服务器端:

     1 import java.io.IOException;
     2 import java.net.Inet4Address;
     3 import java.net.ServerSocket;
     4 import java.net.Socket;
     5 
     6 /*
     7  * 基于TCP协议的Socket通信,实现用户登陆
     8  * 服务器端
     9  */
    10 public class Server {
    11 
    12     public static void main(String[] args) {
    13         try {
    14             // 创建一个服务器端的Socket,即ServerSocket,指定绑定的端口,并监听此端口
    15             @SuppressWarnings("resource")
    16             ServerSocket serverSocket=new ServerSocket(8888);
    17             //记录客户端的数量
    18             int count =0 ;
    19             System.out.println("***服务器即将启动,等待客户端的连接***");
    20             Socket socket=null;
    21             while (true){
    22                 //调用accept()方法开始监听,等待客户端的连接
    23                 socket=serverSocket.accept();    
    24                 //创建一个新的线程
    25                 ServerThread serverThread =new ServerThread(socket);
    26                 //启动线程
    27                 serverThread.start();
    28                 
    29                 count++;//统计客户端的数量
    30                 System.out.println("客户端的数量"+count);
    31                 Inet4Address address=(Inet4Address) Inet4Address.getLocalHost();
    32                 System.out.println("当前客户端的IP:"+address.getHostAddress());
    33             }
    34 
    35         } catch (IOException e) {
    36             // TODO Auto-generated catch block
    37             e.printStackTrace();
    38         }
    39 
    40     }
    41 
    42 }

    客户端:

     1 import java.io.BufferedReader;
     2 import java.io.IOException;
     3 import java.io.InputStream;
     4 import java.io.InputStreamReader;
     5 import java.io.OutputStream;
     6 import java.io.PrintWriter;
     7 import java.net.Socket;
     8 import java.net.UnknownHostException;
     9 
    10 /*
    11  * 客户端
    12  */
    13 public class Client {
    14     public static void main(String[] args) {
    15         try {
    16             //1.创建客户端Socket,指定服务器地址和端口
    17             Socket socket =new Socket("localhost",8888);
    18             //2.获取输出流,向服务器发送信息
    19             OutputStream os =socket.getOutputStream();//字节输出流
    20             PrintWriter pw= new PrintWriter(os);//将输出流包装为打印流
    21             pw.write("用户名:admin;密码:123");
    22             pw.flush();
    23             socket.shutdownOutput();//关闭输出流
    24             
    25             //3.获取输入流,并读取服务器端的响应信息
    26             InputStream is =socket.getInputStream();
    27             BufferedReader br=new BufferedReader(new InputStreamReader(is));
    28             String info=null;
    29             while((info=br.readLine())!=null){
    30                 System.out.println("我是客户端,服务器说: "+info);
    31             }
    32             socket.shutdownInput();//关闭输入流
    33             
    34             //4.关闭资源
    35             br.close();
    36             is.close();
    37             pw.close();
    38             os.close();
    39             socket.close();
    40         } catch (UnknownHostException e) {
    41             e.printStackTrace();
    42         } catch (IOException e) {
    43             e.printStackTrace();
    44         }
    45     }
    46 }

    多线程:

     1 import java.io.BufferedReader;
     2 import java.io.IOException;
     3 import java.io.InputStream;
     4 import java.io.InputStreamReader;
     5 import java.io.OutputStream;
     6 import java.io.PrintWriter;
     7 import java.net.Socket;
     8 
     9 /*
    10  * 服务器端线程服处理类
    11  */ 
    12 public class ServerThread extends Thread {
    13     //和本线程相关的Socket
    14     Socket socket=null;
    15     public ServerThread(Socket socket){
    16         this.socket=socket;
    17     }
    18     //线程执行的操作,响应客户端的请求
    19     public void run(){
    20         InputStream is = null;
    21         InputStreamReader isr = null;
    22         BufferedReader br = null;
    23         OutputStream os = null;
    24         PrintWriter pw = null;
    25         try{
    26             //获取一个输入流,并读取客户端所发送的登陆信息
    27             is=socket.getInputStream();//字节输入流
    28             isr =new InputStreamReader(is);//将字节流转换为字符流
    29             br=new BufferedReader(isr);//为输入流添加缓冲
    30             String info=null;
    31             while((info=br.readLine())!=null){
    32                 System.out.println("我是服务器,客户端说: "+info);
    33             }
    34             socket.shutdownInput();//关闭输入流
    35     
    36             //获取输入流,响应客户端的请求
    37             os=socket.getOutputStream();
    38             pw=new PrintWriter(os);
    39             pw.write("欢迎您!");
    40             pw.flush();//调用flush()方法将缓冲输出
    41             socket.shutdownOutput();//关闭输出流
    42         }catch(IOException e){
    43             e.printStackTrace();
    44         }finally{
    45             //关闭资源
    46             try {
    47                 if(pw!=null){
    48                     pw.close();
    49                 }
    50                 if(os!=null){
    51                     os.close();
    52                 }
    53                 if(br!=null){
    54                     br.close();
    55                 }
    56                 if(isr!=null){
    57                     isr.close();
    58                 }
    59                 if(socket!=null){
    60                     socket.close();
    61                 }
    62             } catch (IOException e) {
    63                 // TODO Auto-generated catch block
    64                 e.printStackTrace();
    65             }
    66         }
    67     }
    68     
    69     
    70 }

     通过 Socket 实现 UDP 编程

    服务器端:

     1 import java.io.IOException;
     2 import java.net.DatagramPacket;
     3 import java.net.DatagramSocket;
     4 import java.net.Inet4Address;
     5 
     6 /*
     7  * 服务器端,基于UDP的用户登陆
     8  */
     9 public class UDPserver {
    10     public static void main(String[] args) throws IOException {
    11         //1.创建服务器端DatagramSocket,指定端口
    12         DatagramSocket socket = new DatagramSocket(8800);
    13         //2.创建数据报,用于接收客户端发送的数据
    14         byte[] data =new byte[1024];//创建字节数组,指定接受的数据包的大小
    15         DatagramPacket packet=new DatagramPacket(data, data.length);
    16         //3.接受客户端发送的数据
    17         System.out.println("***服务器已经启动,等待客服端发送数据***");
    18         socket.receive(packet);//此方法在接收到数据报之前会一直阻塞
    19         //4.读取数据
    20         String info=new String(data,0,packet.getLength());
    21         System.out.println("我是服务器,客户端说"+info);
    22         /*
    23          * 向服务器端响应数据
    24          */
    25         //1定义客户端的地址、端口、数据
    26         Inet4Address address=(Inet4Address) packet.getAddress();
    27         int port=packet.getPort();
    28         byte[] data2="欢迎您!".getBytes();
    29         //2.创建数据报,包含响应的数据信息
    30         DatagramPacket packet2=new DatagramPacket(data2, data2.length, address,port);
    31         //3.响应客户端
    32         socket.send(packet2);
    33         //4.关闭资源
    34         socket.close();
    35         
    36         
    37     }
    38 }

    客户端:

     1 import java.io.IOException;
     2 import java.net.DatagramPacket;
     3 import java.net.DatagramSocket;
     4 import java.net.Inet4Address;
     5 
     6 /*
     7  * 客户端
     8  */
     9 public class UDPclient {
    10     public static void main(String[] args) throws IOException {
    11         /*
    12          * 向服务器端发送数据
    13          */
    14         //1.定义服务器的地址、端口号、数据
    15         Inet4Address address=(Inet4Address) Inet4Address.getByName("localhost");
    16         int port=8800;
    17         byte[] data="用户名“admin;密码123".getBytes();
    18         //2.创建数据报,包发送的数据信息
    19         DatagramPacket packet=new DatagramPacket(data, data.length, address,port);
    20         //3.创建DatagramPacket对象
    21         DatagramSocket socket =new DatagramSocket();
    22         //4.向服务器端发送数据报
    23         socket.send(packet);
    24         
    25         /*
    26          * 接受服务器端响应的数据
    27          */
    28         //1.创建数据报,用于接受服务器端相应的数据
    29         byte[] data2=new byte[1024];
    30         DatagramPacket packet2=new DatagramPacket(data2, data2.length);
    31         //2.接受服务器相应的数据
    32         socket.receive(packet2);
    33         //3.读取数据
    34         String reply =new String (data2,0,packet2.getLength());
    35         System.out.println("我是客户端,服务器说: "+reply);
    36         //4.关闭资源
    37         socket.close();
    38     }
    39 }

    TCP与UDP基本区别 

      1.基于连接与无连接
      2.TCP要求系统资源较多,UDP较少; 
      3.UDP程序结构较简单 
      4.流模式(TCP)与数据报模式(UDP); 
      5.TCP保证数据正确性,UDP可能丢包 
      6.TCP保证数据顺序,UDP不保证 
      
    UDP应用场景:
      1.面向数据报方式
      2.网络数据大多为短消息 
      3.拥有大量Client
      4.对数据安全性无特殊要求
      5.网络负担非常重,但对响应速度要求高
     
    具体编程时的区别
       1.socket()的参数不同 
     2.UDP Server不需要调用listen和accept 
     3.UDP收发数据用sendto/recvfrom函数 
     4.TCP:地址信息在connect/accept时确定 
     5.UDP:在sendto/recvfrom函数中每次均 需指定地址信息 
     6.UDP:shutdown函数无效

    基于上述不同,UDP和TCP编程步骤也有些不同,如下:

    TCP: TCP编程的服务器端一般步骤是: 

      1、创建一个socket,用函数socket(); 
      2、设置socket属性,用函数setsockopt(); * 可选 
      3、绑定IP地址、端口等信息到socket上,用函数bind(); 
      4、开启监听,用函数listen(); 
      5、接收客户端上来的连接,用函数accept(); 
      6、收发数据,用函数send()和recv(),或者read()和write(); 
      7、关闭网络连接; 
      8、关闭监听; 

    TCP编程的客户端一般步骤是: 

      1、创建一个socket,用函数socket(); 
      2、设置socket属性,用函数setsockopt();* 可选 
      3、绑定IP地址、端口等信息到socket上,用函数bind();* 可选 
      4、设置要连接的对方的IP地址和端口等属性; 
      5、连接服务器,用函数connect(); 
      6、收发数据,用函数send()和recv(),或者read()和write(); 
      7、关闭网络连接;

    UDP:与之对应的UDP编程步骤要简单许多,分别如下: 

      UDP编程的服务器端一般步骤是: 
      1、创建一个socket,用函数socket(); 
      2、设置socket属性,用函数setsockopt();* 可选 
      3、绑定IP地址、端口等信息到socket上,用函数bind(); 
      4、循环接收数据,用函数recvfrom(); 
      5、关闭网络连接; 

    UDP编程的客户端一般步骤是: 

      1、创建一个socket,用函数socket(); 
      2、设置socket属性,用函数setsockopt();* 可选 
      3、绑定IP地址、端口等信息到socket上,用函数bind();* 可选 
      4、设置对方的IP地址和端口等属性; 
      5、发送数据,用函数sendto(); 
      6、关闭网络连接;

  • 相关阅读:
    实验十三 团队作业9:Beta冲刺与团队项目验收
    《你们都是魔鬼吗》团队作业Beta冲刺---第一天
    #《你们都是魔鬼吗》第八次团队作业:第五天Alpha冲刺
    《你们都是魔鬼吗》第八次团队作业:第三天Alpha冲刺
    《你们都是魔鬼吗》第八次团队作业:第四天Alpha冲刺
    《你们都是魔鬼吗》第八次团队作业 第二天Alpha
    《你们都是魔鬼吗》第八次团队作业:第一天Alpha冲刺
    《你们都是魔鬼吗》实验十二 团队作业八:Alpha冲刺
    Redis主从复制实现原理
    Redis数据类型之SDS简单动态字符串
  • 原文地址:https://www.cnblogs.com/superslow/p/9010811.html
Copyright © 2011-2022 走看看