基本套接字TCP和UDP

TCP的Java支持

     协议相当于相互通信的程序间达成的一种约定,它规定了分组报文的结构、交换方式、包含的意义以及怎样对报文所包含的信息进行解析,TCP/IP协议族有IP协议、TCP协议和UDP协议现在TCP/IP协议族中的主要socket类型为流套接字(使用TCP协议)和数据报套接字(使用UDP协议)。

    TCP协议提供面向连接的服务,通过它建立的是可靠地连接。Java为TCP协议提供了两个类:Socket类和ServerSocket类。一个Socket实例代表了TCP连接的一个客户端,而一个ServerSocket实例代表了TCP连接的一个服务器端,一般在TCP Socket编程中,客户端有多个,而服务器端只有一个,客户端TCP向服务器端TCP发送连接请求,服务器端的ServerSocket实例则监听来自客户端的TCP连接请求,并为每个请求创建新的Socket实例,由于服务端在调用accept()等待客户端的连接请求时会阻塞,直到收到客户端发送的连接请求才会继续往下执行代码,因此要为每个Socket连接开启一个线程。服务器端要同时处理ServerSocket实例和Socket实例,而客户端只需要使用Socket实例。另外,每个Socket实例会关联一个InputStream和OutputStream对象,我们通过将字节写入套接字的OutputStream来发送数据,并通过从InputStream来接收数据。


TCP连接的建立步骤

客户端向服务器端发送连接请求后,就被动地等待服务器的响应。典型的TCP客户端要经过下面三步操作:

   1、创建一个Socket实例:构造函数向指定的远程主机和端口建立一个TCP连接;

   2.通过套接字的I/O流与服务端通信;

   3、使用Socket类的close方法关闭连接。


 服务端的工作是建立一个通信终端,并被动地等待客户端的连接。典型的TCP服务端执行如下两步操作:

     1、创建一个ServerSocket实例并指定本地端口,用来监听客户端在该端口发送的TCP连接请求;

     2、重复执行:

           1)调用ServerSocket的accept()方法以获取客户端连接,并通过其返回值创建一个Socket实例;

           2)为返回的Socket实例开启新的线程,并使用返回的Socket实例的I/O流与客户端通信;

           3)通信完成后,使用Socket类的close()方法关闭该客户端的套接字连接。

DEMO

  客户端

[java]  view plain  copy
  1. import java.io.IOException;  
  2. import java.io.InputStream;  
  3. import java.io.OutputStream;  
  4. import java.net.Inet4Address;  
  5. import java.net.Inet6Address;  
  6. import java.net.InetAddress;  
  7. import java.net.NetworkInterface;  
  8. import java.net.Socket;  
  9. import java.net.SocketException;  
  10. import java.net.UnknownHostException;  
  11. import java.util.Enumeration;  
  12.   
  13. public class Exercise {  
  14.     public void tcpExample(){  
  15.         try {  
  16.             Socket socket = new Socket("192.168.138.46",8344);  
  17.             System.out.println("Connection ....to server sending echo string");  
  18.             OutputStream out = socket.getOutputStream();  
  19.             System.out.println("发送数据……");  
  20.             out.write("测试连接并发送数据到服务器成功……".getBytes());  
  21.             socket.close();  
  22.             System.out.println("客户端已经关闭");  
  23.               
  24.         } catch (UnknownHostException e) {  
  25.             // TODO Auto-generated catch block  
  26.             e.printStackTrace();  
  27.         } catch (IOException e) {  
  28.             // TODO Auto-generated catch block  
  29.             e.printStackTrace();  
  30.         }  
  31.           
  32.           
  33.     }  
  34.     public static void main(String[] args) {  
  35.         Exercise e = new Exercise();  
  36.         //e.getInterfaceExample();  
  37.         e.tcpExample();  
  38.           
  39.     }  
  40. }  

服务端
[html]  view plain  copy
  1. package NET;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.InputStream;  
  5. import java.net.ServerSocket;  
  6. import java.net.Socket;  
  7. import java.net.SocketAddress;  
  8.   
  9. public class TCPServer {  
  10.     //设置缓冲区的大小  
  11.     private static final int BUFSIZE = 50;  
  12.       
  13.     public static void tcpsever(){  
  14.         try {  
  15.             ServerSocket serSocket = new ServerSocket(8344);  
  16.             int recvMsgSize = 0;  
  17.             int total=0;  
  18.             byte[] receive =  new byte[BUFSIZE];  
  19.             while(true){  
  20.                 //此方法返回一个服务器的关联socket,用此进行数据交换  
  21.                 Socket clntSock = serSocket.accept();  
  22.                 SocketAddress socadd = clntSock.getRemoteSocketAddress();  
  23.                 System.out.println("clint address:"+socadd);  
  24.                 InputStream in = clntSock.getInputStream();  
  25.                 while((total=in.read(receive, recvMsgSize, BUFSIZE-recvMsgSize))!=-1){  
  26.                     recvMsgSize += total;  
  27.                 }  
  28.                 System.out.println("从客户端收到的数据:"+new String(receive));  
  29.                 clntSock.close();  
  30.                 System.out.println("关闭和此客户端的连接……");  
  31.             }  
  32.               
  33.         } catch (IOException e) {  
  34.             // TODO Auto-generated catch block  
  35.             e.printStackTrace();  
  36.         }  
  37.           
  38.     }  
  39.     public static void main(String args[]){  
  40.         tcpsever();  
  41.     }  
  42.   
  43. }  

UDP的Java支持

    UDP协议提供的服务不同于TCP协议的端到端服务,它是面向非连接的,属不可靠协议,UDP套接字在使用前不需要进行连接。实际上,UDP协议只实现了两个功能:

    1)在IP协议的基础上添加了端口;

    2)对传输过程中可能产生的数据错误进行了检测,并抛弃已经损坏的数据。


    Java通过DatagramPacket类和DatagramSocket类来使用UDP套接字,客户端和服务器端都通过DatagramSocket的send()方法和receive()方法来发送和接收数据,用DatagramPacket来包装需要发送或者接收到的数据。发送信息时,Java创建一个包含待发送信息的DatagramPacket实例,并将其作为参数传递给DatagramSocket实例的send()方法;接收信息时,Java程序首先创建一个DatagramPacket实例,该实例预先分配了一些空间,并将接收到的信息存放在该空间中,然后把该实例作为参数传递给DatagramSocket实例的receive()方法。在创建DatagramPacket实例时,要注意:如果该实例用来包装待接收的数据,则不指定数据来源的远程主机和端口,只需指定一个缓存数据的byte数组即可(在调用receive()方法接收到数据后,源地址和端口等信息会自动包含在DatagramPacket实例中),而如果该实例用来包装待发送的数据,则要指定要发送到的目的主机和端口。


UDP的通信建立的步骤

UDP客户端首先向被动等待联系的服务器发送一个数据报文。一个典型的UDP客户端要经过下面三步操作:

    1、创建一个DatagramSocket实例,可以有选择地对本地地址和端口号进行设置,如果设置了端口号,则客户端会在该端口号上监听从服务器端发送来的数据;

    2、使用DatagramSocket实例的send()和receive()方法来发送和接收DatagramPacket实例,进行通信;

    3、通信完成后,调用DatagramSocket实例的close()方法来关闭该套接字。


由于UDP是无连接的,因此UDP服务端不需要等待客户端的请求以建立连接。另外,UDP服务器为所有通信使用同一套接字,这点与TCP服务器不同,TCP服务器则为每个成功返回的accept()方法创建一个新的套接字。一个典型的UDP服务端要经过下面三步操作:

1、创建一个DatagramSocket实例,指定本地端口号,并可以有选择地指定本地地址,此时,服务器已经准备好从任何客户端接收数据报文;

    2、使用DatagramSocket实例的receive()方法接收一个DatagramPacket实例,当receive()方法返回时,数据报文就包含了客户端的地址,这样就知道了回复信息应该发送到什么地方;

    3、使用DatagramSocket实例的send()方法向服务器端返回DatagramPacket实例。

UDP Socket Demo

这里有一点需要注意:

UDP程序在receive()方法处阻塞,直到收到一个数据报文或等待超时。由于UDP协议是不可靠协议,如果数据报在传输过程中发生丢失,那么程序将会一直阻塞在receive()方法处,这样客户端将永远都接收不到服务器端发送回来的数据,但是又没有任何提示。为了避免这个问题,我们在客户端使用DatagramSocket类的setSoTimeout()方法来制定receive()方法的最长阻塞时间,并指定重发数据报的次数,如果每次阻塞都超时,并且重发次数达到了设置的上限,则关闭客户端。


DEMO‘

[java]  view plain  copy
  1. package NET;  
  2.   
  3. import java.io.IOException;  
  4. import java.net.DatagramPacket;  
  5. import java.net.DatagramSocket;  
  6. import java.net.Inet4Address;  
  7. import java.net.InetAddress;  
  8. import java.net.Socket;  
  9. import java.net.SocketException;  
  10. import java.net.UnknownHostException;  
  11.   
  12. import com.sun.jmx.snmp.InetAddressAcl;  
  13.   
  14. public class UDP {  
  15.     private final static int  TIMEOUT = 3000;  
  16.     private final static int BUFSIZE = 50;  
  17.     private final static int tries = 5;  
  18.     /** 
  19.      * udp连接的客户端 
  20.      * @throws SocketException  
  21.      * @throws UnknownHostException  
  22.      */  
  23.     public void udpclnt() throws SocketException, UnknownHostException{  
  24.         int tril = 0;  
  25.         DatagramSocket socket = new DatagramSocket();  
  26.         String art = "UDP连接测试成功……";  
  27.         byte[] by = art.getBytes();  
  28.         InetAddress address = null;  <li class="alt" style="border-top: none; border-right: none; border-bottom: none; border-left: 3px solid rgb(108, 226, 108); border-image: initial; list-style-type: decimal-leading-zero; list-style-image: initial; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !impo
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值