黑马程序员技术交流社区

标题: 学习笔记java之UDP Socket编程 [打印本页]

作者: 小罴孩    时间: 2013-7-30 09:39
标题: 学习笔记java之UDP Socket编程
网络通信三要素
通信条件是两个主机通信,这两个主机必须装有相同的通讯协议。
1、  IP地址:网络设备中的标识,用于找到对方IP。不容易记忆,可用主机名。本地回环地址 127.0.0.1 主机名:localhost
2、  端口号:数据发送到对方指定的应用程序上,为了标识这些应用程序,所以给这网络应用程序都用数字标识,称这些数字为端口(逻辑端口)。
用于标识不同进程的逻辑地址,有效端口为:0~65535,其中0~1024为系统使用或保留端口
3、  传输协议:定义通信规则,这个通信规则称为协议。国际组织定义了通用协议TCP/IP。
TCP和UDP
UDP(User Date Protocol)用户数据报协议:
         1、将数据封装成数据包中,不需要建立连接
         2、每个数据报的大小限制在64k内
         3、因无连接,是不可靠协议
         4、不需要建立连接,速度快
面向无连接协议,在发送信息时不需要建立连接,在生活中就像到邮局中邮寄包裹一样,只需要知道对方地址即可,是单方面的发送。这样发送的速度很快,但有可能丢掉一些数据包,在线看视屏就是用UDP协议(下载、聊天、视屏会议、桌面共享)。固话机相当于UDP
TCP(Transmission Control Protocol)传输控制协议:
1、  建立连接,形成传输数据的通道
2、  在连接中进行大数据传输
3、  通过三次握手完成连接,是可靠协议
4、  必须建立连接,效率会稍低
打电话就相当于TCP传输
TCP是主机对主机层的传输控制协议,提供可靠的连接服务,采用三次握手确认建立一个连接:

位码即tcp标志位,有6种标示:SYN(synchronous建立联机) ACK(acknowledgement 确认) PSH(push传送) FIN(finish结束) RST(reset重置) URG(urgent紧急)

Sequence number(顺序号码) Acknowledge number(确认号码)

第一次握手:主机A发送位码为syn=1,随机产生seq number=1234567的数据包到服务器,主机B由SYN=1知道,A要求建立联机;

第二次握手:主机B收到请求后要确认联机信息,向A发送ack number=(主机A的seq+1),syn=1,ack=1,随机产生seq=7654321的包

第三次握手:主机A收到后检查ack number是否正确,即第一次发送的seq number+1,以及位码ack是否为1,若正确,主机A会再发送ack number=(主机B的seq+1),ack=1,主机B收到后确认seq值与ack=1则连接建立成功。

完成三次握手,主机A与主机B开始传送数据。

网络模型

两台主机之间的通信,就是数据的包装与解包的过程,程序发出数据,经过 应用层—》表示层—》会话层—》传输层—》网络层—》数据连接层—》物理层 的一系列数据包装让后通过网线、光纤、无线网等传送到另一台主机上,然后是解包的过程(与包装相反),最后通过端口识别是用哪个程序来处理这段信息。
传输协议
IP地址:如何获取本机地址
import java.net.InetAddress;
public classTest1 {
   public static void main(String[] args) {
      InetAddress ia = null;
      try {
         ia = InetAddress.getLocalHost();
      } catch(Exception e) {
         System.out.println("err!");
      }
      //输出主机IP地址
      System.out.println(ia.getHostAddress());
      //输出主机名
      System.out.println(ia.getHostName());
   }
}
拿到任何一台主机IP地址getByName(String host)通过主机名获取主机IP地址
如果IP地址和对应的主机名没有在网络上,程序虽然可以找到这个IP地址,但是无法解析成功,则主机名字还是IP地址。
import java.net.InetAddress;
import java.net.UnknownHostException;
public classTest2 {
   public static void main(String[] args) throws UnknownHostException {
      //获取主机名下的所有IP地址,一个IP地址数组
      InetAddress[] i = InetAddress.getAllByName("www.baidu.com");
      for(Object o:i){
         System.out.println(o);
      }
      System.out.println();
      //获取一个IP地址
      InetAddress ip = InetAddress.getByName("www.baidu.com");
      System.out.println(ip);
   }
}
获取主机名需要解析,还是获取IP地址效率更高一些

Socket网络编程
         Socket就是网络服务提供的一种机制
         通信的两端都有Socket
         网络通信其实就是Socket间的通信
         数据在两个Socket之间通过IO传输

1、  通过UDP传输方式,将一段文字数据发送出去
a)         建立UDP的Socket服务
b)         提供数据,并将数据封装到数据包中
c)         通过Socket服务的发送功能,将数据包发送出去
d)         关闭资源
import java.net.*;
public classSocketTest {
   public void go() throws Exception {
      //创建UDP服务,指定端口为8888
      DatagramSocket ds = newDatagramSocket(8888);
      //创建并封装数据报
      byte[] buf = "forever not along".getBytes();
      InetAddress i = InetAddress.getByName("127.0.0.1");
      DatagramPacket dp = newDatagramPacket(buf, buf.length,i,55555);
      try {
         //发送数据
         ds.send(dp);
         System.out.println("发送成功!");
      } catch(Exception e) {
         System.out.println("发送失败!");
      } finally{
         System.out.println("关闭系统资源");
         ds.close();
      }
   }
   public static void main(String[] args) throws Exception {
      SocketTest st = newSocketTest();
      st.go();
   }
}

2、  UDP接收端
a)         建立UDP服务
b)         定义一个数据包,用来存储接收到的字节数据,因为数据包对象中有更多功能可以提取字节数据中的不同数据信息
c)         通过Socket服务的receive方法将接受到的数据存入已定义好的数据包中
d)         通过数据包对象的特有功能,将这些不同的数据去除
e)         关闭资源
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public classUdpReceive {
   public static void main(String[] args) throws Exception{
      //定义UDP的Socket服务
      DatagramSocket ds = newDatagramSocket(55555);
      //定义一个数组缓存
      byte[] buf = new byte[1024];
      //定义接收数据包
      DatagramPacket dp = newDatagramPacket(buf, buf.length);
      ds.receive(dp);
      //通过数据包的方法获取数据
      String ip = dp.getAddress().getHostAddress();
      System.out.println(ip);
      String str = newString(dp.getData(),0,dp.getLength());
      System.out.println(str);
      int port = dp.getPort();
      System.out.println(port);
      ds.close();
   }
}
作者: 许庭洲    时间: 2013-8-7 07:06
值得学习ing!




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2