黑马程序员 网络编程

java培训、android培训期待与您交流!

                                                                                                      网络编程
传输协议:UDP与TCP
UDP:将数据源和目的封装在数据包中(每个数据包的大小在64k以内),不需要建立连接,传输速度快,可以不需要对方在线,但不够安全。通常用于视频等大流量数据传输
TCP:传输效率低,对方必须在在线,否则数据会丢失,安全(因为需要三次握手:你在不?我在!哦,我知道了!)
UDP相对于TCP而言,是缺少一个可靠的丢失重发机制,因此可以立即返回,所以你觉得快
UDP属于发射后不管,但是从IP层来说,它的效率和TCP相比,几乎相同

TCP为什么慢呢?就是因为需要 发射 确认 这样一个循环过程,所以慢

现在喜欢用UDP代替TCP的原因主要是 TCP的重发机制不完美,等待时间不合理,响应经常偏慢

UDP的问题主要在于丢包,如果你的API层协议规定部分数据可以丢失,那么UDP的响应速度会是最好的选择
同样,如果规定绝对不可以丢包,那么需要你自己在API或者引擎里负责处理UDP的可靠传输
一般测试下,在相对可靠的环境里,UDP的丢包率很低,因此即使采用确认模式传输,速度也很快
但是,如果在INTERNET上,例如 电信到CNC线路,丢包率是偏高的,效率会严重降低,CPU开销剧烈增加[主要是确认机制导致的]
   Socket是为网服务提供的一种机制,在通信的两端都有Socket间的通信,网络通信就是Socket间的通信,数据在两个Socket间通过IO传输来完成。
   UDP传输:
   1:UDP传输需要两个对象:DatagramSocket(UDPsocket服务)和DatagramPacket(数据包对象)
   2:建立发送端和接收端(发送端与接收端是两个独立运行的程序,也就是需要建立两个主函数)
   3:建立数据包
   4:调用Socket的发送(send)和接受方法
   5:关闭Socket资源
   import java.net.*;
   //发送端
   class Send
   {
 public static void main(String[] args)
 {
        //建立Socket服务
 DatagramSocket ds = new DatagramSocket();
        准备数据,需要的是字节数组
 byte[] buf = "UDP,哥们来了!".getBytes();
 //将数据封装成数据包对象。既然用来发送,所以数据包对象必须要明确目的地址和端口
 DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAdress.getByname("192.168.54.2"),1232);//发送buf中的数据,且长度为该字节数组的长度,获取一个IP地址,确定一个发送端口(1232)
 //使用UDP中的Socket服务的send方法将数据包发出
        ds.send(dp);
 //关闭资源
 ds.close();
 }
    }
  
   /*
   接收端:
   1,建立UDP的Socket服务。为了明确接收端要处理哪部分数据,所以要给接收端一个具体的数字端口,来监听一个具体的端口,只要给这个端口发送数据,接收端就会有相 应的应用程序来解析
   2,准备好一个数据包用来存放接收到的字节数据,并通过数据包对象的方法对该数据包中的数据进行解析
   3,使用UDP中的接受方法,将接收到的数据都储存到准备好的数据包中
   4,将接收到的数据解析出来,并打印在控制台上
   5,关闭资源

  
  
   class Rece
   {
       public static void main(String[] args)
       {
  //创建UDP的接收端的Socket服务,确定要接受的端口
  DatagramSocket ds = new DatagramSocket(1232);
  //准备好一个用于存储接收到的数据的数据包
  byte[] buf = new byte[1024];
  DatagramPacket dp = new DatagramSocket(buf,buf.length);
  //使用UDP的Socket服务的接受方法,将接收到的数据储存到数据包中
  ds.receive(dp);//阻塞式方法
  //通过数据包对象的方法获取数据包中的数据,同时获取包的数据
  String ip = dp.getAddress().getHostAddress();
  int port = dp.getPort();
  String text = new String(dp.getData(),0,dp.getLength());
  System.out.println(ip+":"text+".."+port);
  ds.close;
       }
    }
    以上是两个线程,可以在编译前通过start再开启一个线程。最好先运行接收端,这样可以避免丢包。且一个端口一次只能接受一条信息,随着条数的增多,发送端口数会依次增多。
         群聊程序
    思路:该程序既可以发送数据,又可以接受数据,这样也可以同时进行,所以要用到多线程技术(一个负责发送,一个负责接收)。需要用到两个run方法进行线程的封装,并且同时封装到两个实现了Runnable的接口类中。
    import java.io.*;  //用于读取键盘
    import java.net.*;
    class Send implements Runnable
    {
 private DatagramSocket ds;
 Send(DatagramSocket ds)
 {
  this.ds = ds;
 }
 public void run()
 {
  try
  {
   BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));//键盘读取高效录入
   String line = null;
   while((line=bufr.readLine())!=null)
   {
   byte[] buf = line.getBytes();
   DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAdress.getByName("192.168.54.255"),1232);//将录入的数据打包,发送地址及端口
   ds.send(dp);//将打包后的数据发送出去
   //如果发送的是886就结束程序
   if("886".equals(line));
    break;
   }
  }
  ds.close();//关闭流资源
  }
  catch(Exception e)
  {
  throw new RuntimeException("发送失败!");
  }
 }
     }
     class Race implements Runnable
     {
 private DatagramSocket ds;
        Race(DatagramSocket ds)
 {
  this.ds = ds;
 }
 public void run()
 {
     try
     {
  while(true)//可以多次接受数据
  {
   byte[] buf = new byte[1024];
   DatagramPacket dp new DatagramPacket(buf,buf.length);//操作数组中的数据
   ds.receive(dp);//将数据打包
   String ip = dp.getAddress().getHostAddress();//获取包的ip地址   
   String text = new String(dp.getData(),0,dp.getLength());//获取数据所在的数组,并获取该数组长度的全部数据
   System.out.println(ip+":"+text);
   if(text.equals("886"))
   {
    System.out.println(ip+"...退出聊天室");
   }
  }
     }
 
 catch(Exception e)
 {
  throw new RunntimeException("接收端失败!");
 }
 }
      }
     class ChatDemo
     {
 public static void main(String[] args)
 {
  DatagramSocket send = new DatagramSocket();
  DatagramSocket race = new DatagramSocket(1232);
  new Thread(new Send(send).start();
  new Thread(new Send(rece).start();
 }
 }

java培训、android培训期待与您交流!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
黑马程序员是一家IT培训机构,提供各种技术培训课程,包括网络通信相关的课程。在网络通信中,socket是一种编程接口,用于实现不同主机之间的通信。通过socket函数创建一个套接字,指定域名、类型和协议。域名可以是AF_INET、AF_INET6或AF_UNIX,类型可以是SOCK_STREAM(用于TCP通信)或SOCK_DGRAM(用于UDP通信),协议可以是0表示自动选择适合的协议。创建成功后,套接字会返回一个文件描述符,用于在后续的通信中进行读写操作。 在TCP通信中,服务器和客户端的流程大致相同。服务器首先使用socket函数创建套接字,然后使用bind函数绑定服务器地址结构,接着使用listen函数设置监听上限。服务器通过accept函数阻塞监听客户端连接,并使用read函数读取客户端传来的数据,进行相应的处理后,使用write函数将处理后的数据写回给客户端,最后使用close函数关闭套接字。客户端也是先使用socket函数创建套接字,然后使用connect函数与服务器建立连接,之后使用write函数将数据写入套接字,再使用read函数读取服务器返回的数据,最后使用close函数关闭套接字。 在UDP通信中,服务器和客户端的流程也有所不同。服务器使用socket函数创建套接字,指定类型为SOCK_DGRAM,然后使用bind函数绑定服务器地址结构。服务器通过recvfrom函数接收客户端传来的数据,并进行相应的处理,最后使用sendto函数将处理后的数据发送回给客户端。客户端同样使用socket函数创建套接字,然后通过sendto函数将数据发送给服务器,再使用recvfrom函数接收服务器返回的数据。 总之,socket网络通信是通过创建套接字实现不同主机之间的通信。根据使用的协议不同,可以选择TCP或UDP通信方式。服务器和客户端根据流程进行相应的操作,实现数据的传输和交互。<span class="em">1</span><span class="em">2</span><span class="em">3</span><span class="em">4</span>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值