黑马程序员_java基础13网络编程 TCP和DNS

来源:互联网 发布:怪物猎人p3武器数据库 编辑:程序博客网 时间:2024/05/19 18:45

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

day24***tcp***************************************************

@@TCP 传输
1,Socket和ServerSocket
2,建立客户端和服务器端
3,建立连接后,通过Socket中的IO流进行数据的传输。
4,关闭Socket
5,客户端和服务器端是两个独立的应用程序。

@@Socket类用来创建tcp协议的客户端
此类实现客户端套接字(也可以就叫“套接字”)。套接字是两台机器间通信的端点。
构造方法
  Socket(String host, int port)
          创建一个流套接字并将其连接到指定主机上的指定端口号。
  Socket()
          通过系统默认类型的 SocketImpl 创建未连接套接字
   {用下面的函数进行连接服务器端!
   void connect(SocketAddress endpoint)
          将此套接字连接到服务器。
    void connect(SocketAddress endpoint, int timeout)
          将此套接字连接到服务器,并指定一个超时值。
   }
  Socket(InetAddress address, int port)
          创建一个流套接字并将其连接到指定 IP 地址的指定端口号。


方法摘要
InetAddress getInetAddress()
          返回套接字连接的地址。(即对方的地址)
 InputStream getInputStream()
          返回此套接字的输入流。
 OutputStream getOutputStream()
          返回此套接字的输出流。
 int getPort()
          返回此套接字连接到的远程端口。
 void shutdownInput()
          此套接字的输入流置于“流的末尾”。
 void shutdownOutput() //关闭输出流。相当于给流中加入一个结束标记-1.让对方知道输出流已结束!
          禁用此套接字的输出流。
 void close()
          关闭此套接字。
@@ServerSocket类用来创建tcp协议的服务器端
此类实现服务器套接字。服务器套接字等待请求通过网络传入。
它基于该请求执行某些操作,然后可能向请求者返回结果。
构造方法
 ServerSocket()
          创建非绑定服务器套接字。
   {用下面方法完成绑定指定客户端
    void bind(SocketAddress endpoint)
           将 ServerSocket 绑定到特定地址(IP 地址和端口号)。
    void bind(SocketAddress endpoint, int backlog)
           将 ServerSocket 绑定到特定地址(IP 地址和端口号)。
   }
 ServerSocket(int port)
          创建绑定到特定端口的服务器套接字。
  ServerSocket(int port, int backlog) //backlog最大连接个数,一般是50
          利用指定的 backlog 创建服务器套接字并将其绑定到指定的本地端口号。
  ServerSocket(int port, int backlog, InetAddress bindAddr)
          使用指定的端口、侦听 backlog 和要绑定到的本地 IP 地址创建服务器。

方法摘要
 Socket accept()
          侦听并接受到此套接字的连接。
 InetAddress getInetAddress()
          返回此服务器套接字的本地地址。
 int getLocalPort()
          返回此套接字在其上侦听的端口。
例1 从客户端发送一次数据到服务器端,服务端反馈一次信息。
import java.io.*;
import java.net.*;
class TcpClient//客户端发送一段数据给服务器端
{
 public static void main(String[] args)throws Exception
 {
  //创建客户端的socket服务。指定目的主机和端口
  Socket s = new Socket("127.0.0.1",10003);
  //为了发送数据,应该获取socket流中的输出流。
  OutputStream out  = s.getOutputStream();
  out.write("shuju".getBytes());
  s.close();
 }
}
class TcpServer
{
 public static void main(String[] args)throws Exception
 {
  ServerSocket ss = new ServerSocket(10003);//监听端口
  //通过accept方法获取连接过来的客户端对象。
  Socket s = ss.accept();
  String ip = s.getInetAddress().getHostAddress();
  System.out.println(ip);
  //获取客户端发送过来的数据,那么要使用客户端对象的读取流来读取数据。
  InputStream in = s.getInputStream();
  byte[] buf = new byte[1024];
  int len = in.read(buf);
  System.out.println(new String(buf,0,len));
  OutputStream out = s.getOutputStream();
  s.close();//服务端不关自己,但会关闭客户端.
 }
 }
}
例 2 @@从客户端发数据给服务端,服务端返回数据的大写!
import java.io.*;
import java.net.*;
class TcpClient
{
 public static void main(String[] args)throws Exception
 {
  Socket s = new Socket("127.0.0.1",10004);
  //客户端的数据来源!
  BufferedReader bufr =
   new BufferedReader(new InputStreamReader(System.in));

  //创建Socket的IO流!
  BufferedWriter out =
   new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
  //还可以PrintWriter PWout = new PrintWriter(s.getOutputStream(),true);
  //true代表调用println、printf 或 format方法时,自动刷新!

  BufferedReader in =
   new BufferedReader(new InputStreamReader(s.getInputStream()));

  String line = null;
  while((line=bufr.readLine())!=null)//客户端的数据
  {
   if("over".equals(line))
    break;
   out.write(line);//将数据发给服务端!
   out.newLine();//记得加结束标记!
   out.flush();//记得刷新!

   //还可以PWout.println(line);

   //接受服务器返回的数据!
   String str = in.readLine();
   System.out.println("服务端返回的数据:"+str);
  }
  bufr.close();
  s.close();//在Socket流中加了-1,即结束标记!
 }
}
class TcpServer
{
 public static void main(String[] args)throws Exception
 {
  ServerSocket ss = new ServerSocket(10004);     
  Socket s = ss.accept(); 
  //看客户端连接上了吗?
  String ip = s.getInetAddress().getHostAddress();
  System.out.println(ip+"连接上了");
  
  //创建Socket的IO流!
  BufferedReader in =
   new BufferedReader(new InputStreamReader(s.getInputStream()));
  BufferedWriter out =
   new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
  //还可以PrintWriter PWout = new PrintWriter(s.getOutputStream(),true);
  //true代表调用println、printf 或 format方法时,自动刷新!

  String line = null;
  while((line=in.readLine())!=null)//读取客户端发来的数据
  {
   out.write(line.toUpperCase());//将数据处理后,再发给客户端
   out.newLine();//记得结束标记!
   out.flush();//记得刷新!

   //还可以PWout.println(line);
  }
  s.close();
  ss.close(); 
 }
}
/*
该例子出现的问题。
现象:客户端和服务端都在莫名的等待。
为什么呢?
因为客户端和服务端都有阻塞式方法。这些方法么没有读到结束标记。那么就一直等
而导致两端,都在等待。
*/
例 3
@@并发上传图片
import java.net.*;
import java.io.*;
class PicClient
{
 public static void main(String[] args)throws Exception
 {
  
  if(args.length!=1)
  {
   System.out.println("请选择一个图片文件");
   return ;
  }
  File file = new File(args[0]);
  if(!(file.exists()&&file.isFile()))
  {
   System.out.println("文件不存在,或目录有问题");
   return ;
  }
  if(!(file.getName().endsWith(".jpg")))
  {
   System.out.println("文件格式不对!");
   return ;
  }
  if(file.length()>1024*1024*5)
  {
   System.out.println("文件太大,要少于5M");
   return ;
  }
  Socket s = new Socket("127.0.0.1",10006);
  FileInputStream  fis = new FileInputStream(file);
  OutputStream out = s.getOutputStream();
  byte[] buf = new byte[1024];
  int len = 0;
  while((len=fis.read(buf))!=-1)
  {
   out.write(buf,0,len);
  }
  s.shutdownOutput();
  InputStream in = s.getInputStream();
  byte[] bufIn = new byte[1024];
  int num = in.read(bufIn);
  System.out.println(new String(bufIn,0,num));
  
  fis.close();
  s.close();

 }
}
class PicThread implements Runnable
{
 private Socket s ;
 PicThread(Socket s)
 {
  this.s = s;
 }
 public void run()
 {
  int count = 1;
  String ip = s.getInetAddress().getHostAddress();
  try
  {
   System.out.println(ip+"...connected");
   InputStream in = s.getInputStream();
   File file = new File(ip+".jpg");
   while(file.exists())
    file = new File(ip+"("+(count++)+")"+".jpg");
   FileOutputStream fos = new FileOutputStream(file);
   byte[] buf = new byte[1024];
   int len = 0 ;
   while((len=in.read(buf))!=-1)
   {
    fos.write(buf,0,len);
   }
   OutputStream out = s.getOutputStream();
   out.write("上传成功".getBytes());
   fos.close();
   s.close();
   //ss.close();
  }
  catch (Exception e)
  {
   throw new RuntimeException(ip+"上传失败");
  }
 }
}
class PicServer
{
 public static void main(String[] args)throws Exception
 {
  ServerSocket ss = new ServerSocket(10006);
  while(true)
  {
   Socket s = ss.accept();
   new Thread(new PicThread(s)).start();
  }
 }
}
例 4  @@登录检验 userLogin


import java.io.*;
import java.net.*;
class  LoginClient
{
 public static void main(String[] args) throws Exception
 {
  Socket s = new Socket("127.0.0.1",10008);

  BufferedReader bufr =
   new BufferedReader(new InputStreamReader(System.in));

  PrintWriter out = new PrintWriter(s.getOutputStream(),true);

  BufferedReader in =
   new BufferedReader(new InputStreamReader(s.getInputStream()));

  for(int x =0 ;x<3;x++)
  {
   String line = bufr.readLine();
   if(line==null)
    break;
   out.println(line);

   String info = in.readLine();
   
   System.out.println("info:"+info);
   if(info.contains("欢迎"))
    break;
  }
 }
}
class UserThread implements Runnable
{
 private Socket s;
 UserThread(Socket s)
 {
  this.s = s;
 }
 public void run()
 {
  String ip = s.getInetAddress().getHostAddress();
  System.out.println(ip+"...connected");
  try
  {
   for (int x=0;x<3;x++)
   {
    BufferedReader bufIn =
     new BufferedReader(new InputStreamReader(s.getInputStream()));
    String name = bufIn.readLine();
    if(name==null)
     break;
    BufferedReader bufr =
     new BufferedReader(new FileReader("user.txt"));

    PrintWriter out = new PrintWriter(s.getOutputStream(),true);
    
    String line = null;
    boolean flag = false;
    while ((line=bufr.readLine())!=null)
    {
     if(line.equals(name))
     {
      flag = true;
      break;
     }
    }
    if(flag)
    {
     System.out.println(name+",已登录");
     out.println(name+",欢迎光临");
     break;
    }
    else
    {
     System.out.println(name+",尝试登录");
     out.println(name+",用户名不存在!");
     
    }
   }
   s.close();
  }
  catch (Exception e)
  {
   throw new RuntimeException(ip+"校验失败");
  }

 }
}
class  LoginServer
{
 public static void main(String[] args) throws Exception
 {
  ServerSocket ss = new ServerSocket(10008);
  while (true)
  {
   Socket s = ss.accept();

   new Thread(new UserThread(s)).start();
  }
 }
}
@@客户端和服务端
/*
演示客户端和服务端。
1,
客户端:浏览器  dos下: telnet 目的主机ip 端口号
服务端:自定义。

2,
客户端:浏览器。  http//127.0.0.1:8080/myweb(资源路径)/demo.html(资源) 请求服务器的哪些网页
服务端:Tomcat服务器。

D:\apache-tomcat-6.0.30\webapps\myweb
信息网页包 放在webapps包 下面
3,
客户端:自定义。(图形界面)
服务端:Tomcat服务器。
*/
import java.net.*;
import java.io.*;
class ServerDemo
{
 public static void main(String[] args) throws Exception
 {
  ServerSocket ss = new ServerSocket(11000);

  Socket s = ss.accept();
  System.out.println(s.getInetAddress().getHostAddress());
  InputStream in = s.getInputStream();

  byte[] buf = new byte[1024];
  int len = in.read(buf);
  System.out.println(new String(buf,0,len));
  PrintWriter out = new PrintWriter(s.getOutputStream(),true);

  out.println("<font color='red' size='7'>客户端你好</font>");
  s.close();
  ss.close();
 }
}
/**浏览器给服务端发送的信息。http的请求消息头。
http://127.0.0.1:11000/myweb/demo.html(地址栏的数据)
协议://主机名   :端口号/资源路径/资源

1(重)  GET /myweb/demo.html HTTP/1.1(协议版本,还有个1.0)(请求行必须有)
2(重)  Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave
-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msw
ord, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xps
document, application/xaml+xml, */*(其他的也都支持,可以只写这个)(浏览器支持的东西)
3(重)  Accept-Language: zh-cn(接受中文版)
4  User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET
 CLR 2.0.50727; InfoPath.3; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)(用户信息)
5  Accept-Encoding: gzip, deflate(支持的封装形式:gzip压缩,)
6(重)  Host: localhost:11000(服务器我要访问的你的xx主机:端口)(服务器上可以有很多主机)
7  Connection: Keep-Alive(连接状态)
(空行隔开)==必须
请求数据体
 ...
 ...
*/
class MyIE
{
 public static void main(String[] args) throws Exception
 {
  Socket s = new Socket("127.0.0.1",8080);  
  PrintWriter out = new PrintWriter(s.getOutputStream(),true);

  out.println("GET /myweb/demo.html HTTP/1.1");//必须有,其他不是。
  out.println("Accept: */*");
  out.println("Accept-Language: zh-cn");
  out.println("Host: localhost:11000");
  out.println("Connection: Keep-Alive");//另一个状态 :closed

  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();
 }
}
/*MyIE发过去的 http请求数据头!
GET /myweb/demo.html HTTP/1.1
Accept: */*
Accept-Language: zh-cn
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET
 CLR 2.0.50727; InfoPath.3; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)
Accept-Encoding: gzip, deflate
Host: localhost:11000
Connection: Keep-Alive
(空行)**************************一定有的!
请求数据体
*/

/*服务器返回来的 http应答数据头!
HTTP/1.1 200(响应状态码) OK
Server: Apache-Coyote/1.1
Accept-Ranges: bytes
ETag: W/"221-1345432552000"
Last-Modified: Mon, 20 Aug 2012 03:15:52 GMT
Content-Type: text/html
Content-Length: 221
Date: Mon, 20 Aug 2012 04:03:14 GMT
Connection: close
*/
@@URL 封装了socket对象到 URLConnection对象中!
import java.net.*;
class URLDemo
{
 public static void main(String[] args) throws MalformedURLException
 {
  URL url =
new URL("http://127.0.0.1/myweb/demo.html?name=haha&age=30 ");

  System.out.println("getProtocol():"+url.getProtocol());
  System.out.println("getHost():"+url.getHost());
  System.out.println("getPort():"+url.getPort());
  System.out.println("getPath():"+url.getPath());
  System.out.println("getFile():"+url.getFile());
  System.out.println("getQuery():"+url.getQuery());  

  /*int port = url.getPort();
  if(port==-1)//默认为-1
   port=8080;*/
 }
}
/*
 String getFile()
          获取此 URL 的文件名。
 String getHost()
          获取此 URL 的主机名(如果适用)。
 String getPath()
          获取此 URL 的路径部分。
 int getPort()
          获取此 URL 的端口号。
 String getProtocol()
          获取此 URL 的协议名称。
 String getQuery()
          获取此 URL 的查询部分。
*/
class URLConnectionDemo  这个类是将MyIE类中的内容封装了!
{
 public static void main(String[] args) throws Exception
 {
  URL url =
new URL("http://127.0.0.1:8080/myweb/demo.html?name=haha&age=30 ");

  URLConnection conn = url.openConnection();
  //不用写socket,已经连接并封装了,从传输层 到 应用层了!响应头被处理了。
  //只显示需要的资源
  System.out.println(conn);
  //相当于 socket中的方法 s.getInputStream();
  InputStream in = conn.getInputStream();

  byte[] buf = new byte[1024];
  int len = in.read(buf);
  System.out.println(new String(buf,0,len));
 }
}
@@域名解析
http://www.baidu.com:8080/myweb/demo.html(地址栏的数据)

想要将主机名www.baidu.com 翻译成ip地址 需要域名解析,需要DNS域名解析服务器。
浏览器先去公网上找一台DNS,然后找到与百度对应的ip地址,获取该地址。
DNS上都是 网站和 ip地址的 键值对,映射表。
DNS将ip返回给客户机(浏览器),客户机再通过
http://69.5.64.2:8080/myweb/demo.html(地址栏的数据)
来去请求 百度的 网页信息。

其实浏览器最先寻找的是本地记录的信映射表信息。
对于http://127.0.0.1:8080/myweb/demo.html(地址栏的数据)
本地主机有 本地DNS 即本地记录的 域名解析服务器。
c:\windows\system32\drivers\etc中有hosts文件 存有映射关系。
咱自己可以在文件中添加一些映射关系,
 1--来避免一些软件去它的官网更新(它想检查你的注册码的正确性)
  127.0.0.1 它的官网
 2--来添加 127.0.0.1  木马网站 来避免木马网站修改IE主页。

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

原创粉丝点击