zoukankan      html  css  js  c++  java
  • Java学习---TCP Socket的学习

    基础知识

    1. TCP协议

          TCP是一种面向连接的、可靠的、基于字节流的运输层(Transport layer)通信协议。在简化的计算机网络OSI模型中,它完成第四层传输层所指定的功能,UDP是同一层内另一个重要的传输协议。

    TCP所提供服务的主要特点面向连接的传输;端到端的通信;高可靠性,确保传输数据的正确性,不出现丢失或乱序;全双工方式传输;采用字节流方式,即以字节为单位传输字节序列;紧急数据传送功能

           TCP支持的服务:文件传送File Transfer;远程登录Remote login;计算机邮件Mail;网络文件系统(NFS);远程打印(Remote printing);远程执行(Remote execution);名字服务器(Name servers);终端服务器(Terminal servers)。

        2. 端口

           TCP/IP协议中提出了端口(port)的概念,用于标识网络主机上通信的软件进程。 端口实际上是一个抽象的软件结构(包括一些数据结构和I/O缓冲区)。应用程序(即进程)通过系统调用与某端口建立关联(binding)后,传输层传给该端口的数据都被相应的应用进程所接收。端口又是在网络体系结构中应用进程访问传输服务的入口点SAPService Access Point服务访问点)。

    TCP/IP体系中,用于存储端口号长度为16bit ,取值范围0~65535,它用于存储本地软件进程,所以仅具有本地意义。通常,端口分为:熟知端口,取值范围0~1023,为常用应用进程指定的固定值;一般端口,取值范围1024~49151,供一般程序使用;动态端口:49152~65535供某些默认服务使用,如表1所示。

    1 常用进程和熟知端口

    echo

    7

    验证2台计算机连接有效性

    daytime

    13

    服务器当前时间文本描述

    ftp

    20/21

    21用于命令,20用户数据

    telnet

    23

    远程登录

    smtp

    25

    邮件发送

    whois

    43

    网络管理的目录服务

    dns

    53

    域名解析

    tftp

    69

    小文件传输

    finger

    79

    主机用户信息

    http

    80

    HTTP

    pop3

    110

    邮局协议

    nntp

    119

    网络新闻传输协议, 发布Usenet新闻

    snmp

    161

    网络管理协议

    rip

    520

    路由协议

        3. 套接字

      套接字Socket原意是 “插座”,简单的说就是参与通信两方的一种约定,用套接字中的相关函数来完成通信过程。为了区分不同应用程序进程间的网络通信和连接,主要使用3个参数:通信的目的IP地址、使用的传输层协议(TCPUDP)和使用的端口号,通过将这3个参数结合起来,与一个Socket绑定,应用层就可以和传输层通过套接字接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。通常的表示方式为:SOCKET=(传输协议,IP,Port)

    4 . Netstat

      NetStatDOS命令,是一个监控TCP/IP网络的非常有用的工具,它可以显示路由表、实际的网络连接以及每一个网络接口设备的状态信息.Netstat用于显示与IPTCPUDPICMP协议相关的统计数据,一般用于检验本机各端口的网络连接情况。

    可以通过执行Netstat /help获得该应用程序选项的相关帮助。

    Java语言中,实现TCP 套接字中有两个基础类,分别为:

    l Socket: 建立一个客户端标识

    l ServerSocket: 建立一个服务器端标识

     5. ServerSocket

      该类实现服务器socket,一个服务器socket等待网络上的连接请求。通常操作都是基于这个请求,并且会返回一个结果给请求连接者,其类描述如图2所示。

     

    2 ServerSocket类描述

    ServerSocket构造方法有:

    ServerSocket() 创建一个空的服务端socket

    ServerSocket(int port) 在指定端口创建一个服务端socket,;

    ServerSocket(int port, int backlog) 在指定端口创建一个服务端socket和日志;

    ServerSocket(int port, int backlog, InetAddress bindAddr) 
     在指定端口和地址上创建一个服务端socket和日志。

     6. Socket

      该类实现一个客户端socket,这个socket表示在通信的两台设备之间的端点,其类描述如图3所示。

     

    3 Socket类描述

    Socket构造方法有:

    Socket() 创建一个空的客户端socket

    Socket(InetAddress address, int port) 

    创建一个连接指定远程地址和端口的客户端socket

    Socket(InetAddress address, int port, InetAddress localAddr, int localPort) 

    在本地指定地址和端口,创建一个连接指定远程地址和端口的客户端socket

    Socket(String host, int port) 

    创建一个连接指定主机名称和端口的客户端socket

    Socket(String host, int port, InetAddress localAddr, int localPort) 

    在本地指定地址和端口,创建一个连接指定远程主机名称和端口的客户端socket

    基本工作原理,如图所示。

    1. 启动服务器端ServerSocket,监听指定端口;

    2. 启动客户端Socket,连接服务器端Socket

    3. 服务器端Accept确认连接,建立通信通道;

    4. 建立输入和输出流,进行通信;

    5. 通信完毕,关闭Socket连接。

     

    7. 多线程(Thread

      每个正在系统上运行的程序都是一个进程。每个进程包含一到多个线程。进程也可能是整个程序或者是部分程序的动态执行。线程是一组指令的集合,或者是程序的特殊段,它可以在程序里独立执行。也可以把它理解为代码运行的上下文。所以线程基本上是轻量级的进程,它负责在单个程序里执行多任务。

    Java里面有2个方法实现多线程,不论哪种方法都需要覆盖public void run()方法

      

    1 继承 Thread类,比如
      class MyThread extends Thread {
        public void run() {
        // 这里写上线程的内容
        }
        public static void main(String[] args) {
          // 使用这个方法启动一个线程
          new MyThread().start();
        }
      }
    
    2 实现 Runnable接口
      class MyThread implements Runnable{
        public void run() {
        // 这里写上线程的内容
        }
        public static void main(String[] args) {
          // 使用这个方法启动一个线程
          new Thread(new MyThread()).start();
        }
      }
      一般鼓励使用第二种方法,因为Java里面只允许单一继承,但允许实现多个接口。第二个方法更加灵活。
    

      

    类及方法

    1. ServerSocket

    常用方法

     Socket

    accept() 接受客户端的连接请求;

     void

    bind(SocketAddress endpoint) 绑定到指定的地址和端口;

     void

    close() 关闭该ServerSocket

     InetAddress

    getInetAddress() 获得该ServerSocket的本地地址;

     int

    getLocalPort() 获得本地监听端口;

     int

    getReceiveBufferSize() 获得接收缓存尺寸;

     int

    getSoTimeout() 获得数据包超时时间;

     boolean

    isClosed()判断ServerSocket是否关闭;

     void

    setReceiveBufferSize(int size)设置接收缓存尺寸;

     void

    setSoTimeout(int timeout) 以毫秒设置数据包超时时间;

     String

    toString() 将地址和端口作为字符串返回。

    2. Socket

    常用方法

     void

    bind(SocketAddress bindpoint) 绑定socket在本地;

     void

    close() 关闭该socket;

     void

    connect(SocketAddress endpoint) 连接该socket到服务器上;

     void

    connect(SocketAddress endpoint, int timeout) 连接该socket到服务器并设置超时时间;

     InetAddress

    getInetAddress() 获得该socket连接的地址;

     InputStream

    getInputStream() 获得该 socket的输入流;

     InetAddress

    getLocalAddress() 获得该socket的本地地址;

     int

    getLocalPort()获得该socket的本地端口;

     OutputStream

    getOutputStream()获得该 socket的输出流;

     int

    getPort()获得该 socket的远端端口;

     int

    getReceiveBufferSize() 获得该Socket的接收缓存容量;

     int

    getSendBufferSize()获得该Socket的发送缓存容量;

     int

    getSoTimeout() 获得超时时间;

     boolean

    isClosed() 判断该socket是否关闭;

     boolean

    isConnected() 判断该socket是否连接;

     void

    setKeepAlive(boolean on) 设置该socket的连接状态;

     void

    setReceiveBufferSize(int size) 设置接收缓存容量;

     void

    setSendBufferSize(int size) 设置发送缓存容量;

     void

    setSoTimeout(int timeout) 设置毫秒级的超时时间;

     String

    toString() 将该socket转换为字符串输出。

    代码示例

     对指定IP范围内主机上指定PORT范围进行连接测试 

     1 import java.net.*;     
     2 import java.io.*;
     3 
     4 class myJava{
     5     public static void main(String [] args){
     6         String host = "222.24.16.";       
     7         String host_ip = null;
     8         Socket cs = null;
     9         for(int i=1; i<17; i++){             
    10             host_ip = host + i;
    11             for(int j=0; j<65536; j++){            
    12                 try{
    13                     cs = new Socket(host_ip, j);          
    14                     System.out.println(host_ip + " : " + j);
    15                 }catch(Exception e){                
    16                     System.err.println();
    17                 }
    18             }
    19         }
    20     }
    21 }
    View Code

     简单的单线程,一问一答式通信的TCP ServerTCP Client

    服务端:

     View Code

     客户端:

     1 //客户端
     2 import java.io.*;
     3 import java.net.*;
     4 public class MyClient{
     5     public static void main(String args[]) throws IOException{
     6         Socket comSocket = null;
     7         PrintStream out = null;
     8         DataInputStream in = null;
     9         try{
    10             //建立socket连接
    11             comSocket = new Socket("localhost", 1080);//相指定服务器的端口发出连接请求,注意服务器开放的TCP端口号
    12             //分别对应服务器端的O/I流
    13             in = new DataInputStream(comSocket.getInputStream());
    14             out = new PrintStream(comSocket.getOutputStream());
    15         }catch(UnknownHostException e){
    16             System.err.println("Can't find the Server host");
    17             System.exit(0);
    18         }catch(IOException e){
    19             System.err.println("Can't get I/O for the Connection");
    20             System.exit(0);
    21         }
    22     
    23         DataInputStream stdIn = new DataInputStream(System.in);
    24         String fromServer, fromUser;
    25     
    26         while((fromServer = in.readLine()) != null){
    27             System.out.println("Server:" + fromServer);
    28             if(fromServer.equals("bye")) break;
    29             fromUser = stdIn.readLine();
    30             if(fromUser != null){
    31                 System.out.println("Client:" + fromUser);
    32                 out.println(fromUser);
    33             }
    34         }
    35         out.close();
    36         in.close();
    37         stdIn.close();
    38         comSocket.close();
    39     }
    40 }
    View Code

    探测目标计算机开放的TCP 端口 

     1 import java.io.*;
     2 import java.net.*;
     3 
     4 public class ScanPort{
     5     public static void main(String args[]) throws IOException{
     6         Socket comSocket = null;
     7         
     8         for(int i=0;i<1024; i++){
     9             try{
    10                 //建立socket连接
    11                 comSocket = new Socket("localhost", i);//发出连接请求
    12                 
    13                 System.out.println("Can get I/O for the Connection, Port:" + i);
    14             }catch(UnknownHostException e){
    15                 System.err.println("Can't find the Server host");
    16                 //System.exit(0);
    17             }catch(IOException e){
    18                 System.err.println("Can't get I/O for the Connection, Port:" + i);
    19                 //System.exit(0);
    20             }
    21         }
    22         
    23         try{
    24             comSocket.close();
    25         }catch(Exception e){}
    26     }
    27 }
    View Code

     TCP传输文件

    服务端: 

     1 //采用TCP进行通讯,需要服务器和客户端两个部分,因此程序包含SendFileServer.java和SendFileClient.java两个部分。两个文件的IP,端口都在程序中指定, 传输的文件路径也在程序中指定
     2 ////////////SendFileServer.java
     3 import java.io.FileInputStream;
     4 import java.io.IOException;
     5 import java.io.OutputStream;
     6 import java.net.ServerSocket;
     7 import java.net.Socket;
     8 /*
     9  * 用TCP进行文件传输
    10  * 此文件为服务器文件
    11  * 当接受到客户端的请求之后,先向其传输文件名
    12  * 当客户端接受完毕之后,向客户端传输文件
    13  * */
    14 public class SendFileServer implements Runnable{
    15     // 服务器监听端口
    16     private static final int MONITORPORT  = 12345;
    17     private Socket s ;
    18     public SendFileServer(Socket s) {
    19         super();
    20         this.s = s;
    21     }
    22     public static void server()
    23     {
    24         try {
    25             // 创建服务器socket
    26             ServerSocket ss = new ServerSocket(MONITORPORT);
    27             while(true)
    28             {
    29                 // 接收到一个客户端连接之后,创建一个新的线程进行服务
    30                 // 并将联通的socket传给该线程
    31                 Socket s = ss.accept();
    32                 new Thread(new SendFileServer(s)).start();
    33             }
    34         } catch (IOException e) {
    35             // TODO Auto-generated catch block
    36             e.printStackTrace();
    37         }
    38     }
    39     /**
    40      * @param args
    41      */
    42     public static void main(String[] args) {
    43         // TODO Auto-generated method stub
    44         SendFileServer.server();
    45     }
    46     @Override
    47     public void run() {
    48         // TODO Auto-generated method stub
    49         byte[] buf = new byte[100];
    50         OutputStream os=null;
    51         FileInputStream fins=null;
    52         try {
    53             os = s.getOutputStream();
    54             // 文件路径
    55             String filePath = "/home/newton/cangjie.mp3";
    56             // 文件名
    57             String fileName = "cangjie.mp3";
    58             System.out.println("将文件名:"+fileName+"传输过去");
    59             //先将文件名传输过去
    60             os.write(fileName.getBytes());
    61             System.out.println("开始传输文件");
    62             //将文件传输过去 
    63             // 获取文件
    64             fins = new FileInputStream(filePath);
    65             int data;
    66             // 通过fins读取文件,并通过os将文件传输
    67             while(-1!=(data = fins.read()))
    68             {
    69                 os.write(data);
    70             }
    71             System.out.println("文件传输结束");
    72         } catch (IOException e) {
    73             // TODO Auto-generated catch block
    74             e.printStackTrace();
    75         }finally
    76         {
    77             try {
    78                 if(fins!=null) fins.close();
    79                 if(os!=null)    os.close();
    80                 this.s.close();
    81             } catch (IOException e) {
    82                 e.printStackTrace();
    83             }
    84         }
    85     }
    86 }
    View Code

     客户端:

     1 import java.io.FileOutputStream;
     2 import java.io.IOException;
     3 import java.io.InputStream;
     4 import java.net.InetSocketAddress;
     5 import java.net.Socket;
     6 /*
     7  * 用TCP进行文件传输
     8  * 此文件为客户端文件
     9  * 连接上服务器之后,直接接受文件
    10  * 
    11  * */
    12 public class SendFileClient {
    13     private static final String SERVERIP = "127.0.0.1";
    14     private static final int SERVERPORT = 12345;
    15     private static final int CLIENTPORT = 54321;
    16     /**
    17      * @param args
    18      */
    19     public static void main(String[] args) {
    20         // TODO Auto-generated method stub
    21         // 用来接受传输过来的字符
    22         byte[] buf = new byte[100];
    23         Socket s = new Socket();
    24         try {
    25             // 建立连接
    26             s.connect(new InetSocketAddress(SERVERIP,SERVERPORT), CLIENTPORT);
    27             InputStream is = s.getInputStream();
    28             // 接收传输来的文件名
    29             int len = is.read(buf);
    30             String fileName = new String(buf,0,len);
    31             System.out.println(fileName);
    32             //接收传输来的文件
    33             FileOutputStream fos = new FileOutputStream(fileName);
    34             int data;
    35             while(-1!=(data = is.read()))
    36             {
    37                 fos.write(data);
    38             }
    39             is.close();
    40             s.close();
    41         } catch (IOException e) {
    42             // TODO Auto-generated catch block
    43             e.printStackTrace();
    44         }
    45     }
    46 }
    View Code
  • 相关阅读:
    C++ 动态库导出函数名“乱码”及解决
    ASP.NET 4.5 Bundle组件(捆绑、缩小静态文件)
    MVC4 + WebAPI + EasyUI + Knockout-授权代码维护
    关于Grunt可视化的尝试
    Object-c学习之路三(@class与#import的区别)
    2.1 以指定的次序返回查询结果
    进程序名得到进程ID和句柄与进程的公司名(使用快照和GetPeFileCompany和VerQueryValueW等函数)
    在资源里面画出你的界面
    VS2008下WinRar源码生成dll和 lib总结
    进程占用百分百CPU不卡(从未试过,当别的程序运行的时候,当前程序还会运行吗?)
  • 原文地址:https://www.cnblogs.com/ftl1012/p/9347631.html
Copyright © 2011-2022 走看看