黑马程序员-java-网络编程

---------------------- android培训、 java培训、期待与您交流! ----------------------
 网络传输协议主要有TCP和UDP
UDP:
将数据及源和目的封装成数据包中,不需要建立连接
每个数据报的大小限制在64K
无连接,不可靠的协议
因不需要建立连接,速度快   
TCP:
建立连接,形成传输数据的通道
在连接中进行大数据量传输
通过三次握手完成连接,是可靠协议
因必需建立连接,效率会低

实现两台机器的连接是通过Socket,UDP通过数据包DatagramPacket发送信息,
发送信息前都要建立DatagramSocket.
接受数据包要指明Socket端口,DatagramSocket ds = new DatagramSocket(10000),
比如上面10000端口接受数据。

发送数据包DatagramPacket里面要指明发送的IP和端口号,
DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress
     .getByName("localhost"), 10000);
比如上面指明发送buf字节数组中的内容到本地主机的10000端口     

InetAddress类对象可以获得本地的IP和主机名字, 还可以通过getByName方法
根据名字获得主机地址。
    InetAddress address = InetAddress.getLocalHost();
  System.out.println(address);
  System.out.println(address.getHostName());
  System.out.println(address.getHostAddress());
  InetAddress address1 = InetAddress.getByName("www.baidu.com");
  System.out.println(address1);
上面程序打印:
myhome/169.254.126.92
myhome
169.254.126.92
www.baidu.com/119.75.218.45

下面是通过UDP发送数据的代码:
   DatagramSocket ds = new DatagramSocket();
  BufferedReader bufr = new BufferedReader(new InputStreamReader(
    System.in));
  String line = null;
  while ((line = bufr.readLine()) != null)
  {
   if ("886".equals(line))
    break;
   byte[] buf = line.getBytes();
   DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress
     .getByName("localhost"), 10000);
   ds.send(dp);
  }
  ds.close();

 下面是通过UDP接受数据的代码:
   DatagramSocket ds = new DatagramSocket(10000);
  while (true)
  {
   byte[] buf = new byte[1024];
   DatagramPacket dp = new DatagramPacket(buf, buf.length);
   ds.receive(dp);
   String ip = dp.getAddress().getHostAddress();
   String data = new String(dp.getData(), 0, dp.getLength());
   System.out.println(ip + "-----" + data);
    }
 通过dp.getAddress().getHostAddress()可以得到发送方的IP地址。
 
如果想实现两端的在线聊天可以让接受端和发送端都实现Runnable接口,
然后在每端起2个线程就可以了,UDP不分什么client端和server端,
下面是一端实现的代码:
接受线程
public class UdpClientReceive implements Runnable
{
 private DatagramSocket ds;
  public UdpClientReceive(DatagramSocket ds)
 {
  this.ds = ds;
 }
  public void run()
 {
  while (true)
  {
   byte[] buf = new byte[1024];
   DatagramPacket dp = new DatagramPacket(buf, buf.length);
   try
   {
    ds.receive(dp);
    String ip = dp.getAddress().getHostAddress();
    String data = new String(dp.getData(), 0, dp.getLength());
    System.out.println(ip + "-----" + data);
   }
   catch (IOException e)
   {
    e.printStackTrace();
   }
    }
 }
}
 发送线程:
 public class UdpClientSend implements Runnable
{
 private DatagramSocket ds;
  public UdpClientSend(DatagramSocket ds)
 {
  this.ds = ds;
 }
  public void run()
 {
   BufferedReader bufr = new BufferedReader(new InputStreamReader(
    System.in));
   String line = null;
    try
  {
     while ((line = bufr.readLine()) != null)
   {
        byte[] buf = line.getBytes();
    DatagramPacket dp = new DatagramPacket(buf, buf.length,
      InetAddress.getByName("localhost"), 10002);
    ds.send(dp);
      }
  }
  catch (Exception e)
  {
   e.printStackTrace();
  }
    ds.close();
 }
}

起线程:
public class UdpMainServer
{
  public static void main(String[] args) throws SocketException
 {
  DatagramSocket dssend = new DatagramSocket();
  DatagramSocket dsreceive = new DatagramSocket(10002);
  UdpServerSend send = new UdpServerSend(dssend);
  UdpServerReceive receive = new UdpServerReceive(dsreceive);
  new Thread(send).start();
  new Thread(receive).start();
  }
}
public class UdpMainClient
{
  public static void main(String[] args) throws SocketException
 {
  DatagramSocket dssend = new DatagramSocket();
  DatagramSocket dsreceive = new DatagramSocket(10000);
  UdpClientSend send = new UdpClientSend(dssend);
  UdpClientReceive receive = new UdpClientReceive(dsreceive);
  new Thread(send).start();
  new Thread(receive).start();
    }
 }
 
 TCP连接中,有Server端,Server端会等待客户端的连接,
 ServerSocket ss = new ServerSocket(10000);
 Socket s = ss.accept();
 就是等待10000端口客户端的连接,有客户端Socket s = new Socket(IP, 10000)就产生了一个连接,
 IP为服务端IP的字符串表示形式。
 s.getInputStream()和s.getOutputStream()可以拿到此端口的输入与输出。
 
 下面代码实现连接,客户端发送字母,服务端以大写字母返回。
 public class TransServer
{
  public static void main(String[] args) throws Exception
 {
  ServerSocket ss = new ServerSocket(10000);
  Socket s = ss.accept();
  String ip = s.getInetAddress().getHostAddress();
  System.out.println(ip + ".....connected");
  System.out.println("\n   Server   is   ready   !   \n ");
  PrintWriter out = new PrintWriter(s.getOutputStream(), true);
  BufferedReader bufIn = new BufferedReader(new InputStreamReader(s
    .getInputStream()));
  String line = null;
  while ((line = bufIn.readLine()) != null)
  {
   System.out.println(line);
   out.println(line.toUpperCase());
  }
  s.close();
  ss.close();
   }
}
public class TransClient
{
  public static void main(String[] args) throws IOException
 {
  Socket s = new Socket("127.0.0.1", 10000);
  BufferedReader bufr = new BufferedReader(new InputStreamReader(
    System.in));
  PrintWriter out = new PrintWriter(s.getOutputStream(), true);
  BufferedReader bufIn = new BufferedReader(new InputStreamReader(s
    .getInputStream()));
  String line = null;
  while ((line = bufr.readLine()) != null)
  {
   if ("over".equals(line))
    break;
   out.println(line);
   String str = bufIn.readLine();
   System.out.println("server:" + str);
  }
  }
}
 TCP要实现客户端与服务端的在线聊天,也是分别实现发送和接受线程,
 然后客户端与服务端都起2个线程就可以了,线程都接受socket的引用。
 下面是客户端代码:
 接受数据
 public class ClientInputThread extends Thread
{
 private Socket socket;
 public ClientInputThread(Socket socket)
 {
  this.socket = socket;
 }
 @Override
 public void run()
 {
  try
  {
   InputStream is = socket.getInputStream();
   while(true)
   {
    byte[] buffer = new byte[1024];
    int length = is.read(buffer);
    String str = new String(buffer, 0, length);
    System.out.println(str);
   }
  }
  catch (IOException e)
  {
   e.printStackTrace();
  }
 }
}
发送键盘录入数据
 public class ClientOutputThread extends Thread
{
 private Socket socket;
  public ClientOutputThread(Socket socket)
 {
  this.socket = socket;
 }
  @Override
 public void run()
 {
  try
  {
   OutputStream os = socket.getOutputStream();
     while (true)
   {
    BufferedReader reader = new BufferedReader(
      new InputStreamReader(System.in));
        String line = reader.readLine();
       os.write(line.getBytes());
   }
  }
  catch (IOException e)
  {
   e.printStackTrace();
  }
 }
}
起线程:
public class MainClient
{
 public static void main(String[] args) throws Exception, IOException
 {
  Socket socket = new Socket("127.0.0.1", 4000);
    new ClientInputThread(socket).start();
  new ClientOutputThread(socket).start();
 }
}
 
当我们在浏览器里输入http://127.0.0.1:8080/hello/Login.jsp
表示访问本地主机8080端口下的hello资源下的Login.jsp文件,然后
服务器就会把Login.jsp的信息返回给我们。
当我们在浏览器输入http://www.baidu.com其实是访问百度主机下的
80端口的首页面index.html,然后浏览器会把百度首页面的信息返回给我们,
我们可以通过程序模拟浏览器发出请求的过程:
 如下面的程序请求我本地主机的8080端口Tomcat服务器下hello资源下的jsp页面,
 返回的信息打印到控制台:
    Socket s = new Socket("127.0.0.1", 8080);
  PrintWriter out = new PrintWriter(s.getOutputStream(), true);
  out.println("GET /hello/first.jsp HTTP/1.1");
  out.println("Accept: */*");
  out.println("Accept-Language: zh-cn");
  out.println("Host: 127.0.0.1:8080");
  out.println("Connection: Keep-Alive");
  out.println();
  out.println();
  BufferedReader bufr = new BufferedReader(new InputStreamReader(s
    .getInputStream()));
  String line = null;
  while ((line = bufr.readLine()) != null)
  {
   System.out.println(line);
  }
  s.close();
打印输出:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=FC3BF3D5CF07968FE1EA7A4B60991142; Path=/hello
Content-Type: text/html;charset=UTF-8
Content-Length: 1108
Date: Sun, 06 Nov 2011 07:39:54 GMT
 页面内容……………………………………
 
表示请求采用HTTP1.1协议,请求成功等信息,当我们用浏览器请求的时候,
只返回请求体,请求头的信息给拆包了。

我们还可以把IP信息封装成URL对象,通过API得到具体信息。
  URL url = new URL("http://127.0.0.1:8080/hello/first.jsp?name=haha&age=25");
  System.out.println(url.getProtocol());
  System.out.println(url.getHost());
  System.out.println(url.getPort());
  System.out.println(url.getPath());
  System.out.println(url.getFile());
  System.out.println(url.getQuery());
上面程序打印:
 http
127.0.0.1
8080
/hello/first.jsp
/hello/first.jsp?name=haha&age=25
name=haha&age=25

URL中的openConnection()方法可以返回一个URLConnection对象,
该对象封装了创建连接的过程,拿到远程对象的实际连接,
           URL url = new URL(urlPath);
     URLConnection con = url.openConnection();
     InputStream in = con.getInputStream();
     byte[] buf = new byte[1024];
          String str = null;
     int len;
        while ((len = in.read(buf)) != -1)
     {
      str = new String(buf, 0, len);
     System.out.println(str);
         }

假如上面的urlPath为http://www.baidu.com,则会在控制台打印出
百度首页面的信息。

网络编程主要是通过TCP和UDP协议实现多点之间的通信,与多线程、IO技术
结合应用的比较多,关于这部分的学习就总结到这了,谢谢。

---------------------- android培训、 java培训、期待与您交流! ----------------------详细请查看: http://edu.csdn.net/heima

你可能感兴趣的:(黑马程序员-java-网络编程)