常用基本类

InetAddress是java中表示IP的类。主要用于Socket,ServerSocket,URL,DatagramSocket等
 创建InetAddress用三个静态方法
getByName(String hostname)throws UnknownHostException
 getAllByName(String hostname) throws UnknownHostException
 getLocalHost() throws UnknownHostException
 使用这三个静态方法创建InetAddress的时候,除了使用getByName中传递ip地址外(如果使用getByName传递一个ip会首先创建一个InetAddress不管是否存在,当显示的调用getHostName或者toString的时候才会进行网络连接),都会首先进行网络连接,会根据主机名去连接DNS服务器,来查找对应的主机名和ip,一定要捕获异常处理。
 对于已经创建成功的InetAddress可以获取基本属性,getAddress()返回一个字节数组,可以利用
 int unsigned=signByte<0? signByte+256: signByte转换为int。也可以利用它的长度来判断是IPv4或者IPv6。
 两个InetAddress对象equals的条件是具有相同的IP,不管主机名是否相等
 toString的表现形式为:hostname/ip
URL类,是一个final类,使用的是策略设计模式,协议就是策略。
 构造URL的基本方法URL url=new URL("http://www.baidu.com"),如果创建未支持的协议的URL则会出现MalformedURLException异常。
 URL主要由协议、授权机构、路径、片段标示符和查询字符串表示。
 openStream():连接URL所指向的资源,执行客户端与服务器之间的握手,返回一个可读取的数据
 openConnection():打开指定的URL的socket,返回一个URLConnection(表示一个打开网络资源的连接)
 getContent()
 在利用URL进行发送数据的时候,主要URL中只需出现ASCII中的固定子集,未出现的必须进行编码,利用URLEncoder来编码,要对每一部分编码,再用URLDecoder解析编码
URI类是纯粹的关于资源的标识和URI的解析,它没有网络获取功能,主要用于对于URL进行分析。

基于TCP的Socket编程(Socket和ServerSocket)
客户端Socket建立步骤:
1 利用构造函数创建一个新Socket
2 Socket尝试连接远程主机(在构造函数创建后,该socket就会自动连接远程主机)
3 一旦建立连接,此socket就会进行输入流和输出流操作。连接是全双工,双方可同时发送接受数据
4 当数据传输完毕后,一端就或两端就会关闭连接。HTTP1.0,要求每次请求得到服务器响应后就关闭连接。
创建Socket基本方法Socket socket=new Socket("www.ttt.com",80);一定要捕获异常,当主机名不存在的时候,抛出UnknownHostException异常,其他情况会抛出IOException,可以用来测试某一些端口是否可利用。
 获取Socket的输入流,socket.getInputStream();可以通过这个来获取服务器返回的结果,在其调用read的时候会一直阻塞着。一般均要将其链接到过滤器流或者阅读器。
 写入Socket的输出流,socket.getOutputStream();向服务器发送数据,但是这里务必要每次写入后加上out.write("\r\n\r\n"),out.flush(),关闭输出流。对于每行都要加上"\r\n"
 判断一个socket当前是否打开,需要用如下方式:
 isClose返回false仅在已经被关闭或者从未打开的时候
 isConnected表示曾经打开过
boolean connected=socket.isConnected()&&! socket.isClosed();
SocketAddress类,主要用于存放暂时的Socket连接信息,将上次的连接保存后,下次直接利用connect来连接。创建一个SocketAddress,可以通过其子类InetSocketAddress来创建,
InetSocketAddress,此类实现 IP 套接字地址(IP 地址 + 端口号),
它还可以是一个对(主机名 + 端口号)。
InetSocketAddress(String hostname, int port) ;根据字符串指定的主机名来创建

ServerSocket建立步骤
1 使用ServerSocket()构造函数来在某个端口创建一个ServerSocket
2 ServerSocket使用其accept()监听此端口的所有入站请求。在没有请求的时候,该accept方法会一直阻塞,它会使得整个程序停止执行并且等待,直到有客户端尝试进行连接,此时就会返回一个连接客户端和服务器的Socket对象
3 调用输入输出流类型
4 关闭该Socket对象
5 继续等待
 创建一个ServerSocket的基本方法ServerSocket server=new ServerSocket(1888);会抛出IOException和BindException的异常。
 测试一个ServerSocket是否打开利用 ss.isBound()&& !ss.isClosed()来判断。

简单Socket和Server连接测试
客户端Socket
package com.client;

import java.io.IOException;
import java.io.*;
import java.net.Socket;
import java.net.UnknownHostException;

public class FirstClient {
public static void main(String[] args) {
// TODO Auto-generated method stub
   Socket client= null;
try{
     client= new Socket( "localhost",6666);
     InputStream in=client.getInputStream();

     OutputStream outs=client.getOutputStream();
     BufferedOutputStream buffs= new BufferedOutputStream(outs);
     Writer out= new OutputStreamWriter(buffs);
     out.write( "hello===");
//out.flush();
     out.close();
//一定要关闭输出流,否则它会一直占用该端口以及资源
   } catch(UnknownHostException e)
   {
     e.printStackTrace();
   } catch(IOException e)
   {
     e.printStackTrace();
   }
 }
}
服务器端Socket
package com.server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class FirstServer {
public static void main(String[] args) {
// TODO Auto-generated method stub

try {
     ServerSocket server = new ServerSocket(6666);
while ( true) {
       Socket client = null;
try {
         client = server.accept();

         InputStream ins = client.getInputStream();
         BufferedReader read = new BufferedReader(
new InputStreamReader(ins));
         String res = read.readLine();
         read.close();
         System.out.println( "client request:" + res);
       } catch (IOException e) {
         e.printStackTrace();
       } finally {
try {
if (client != null)
             client.close();
         } catch (IOException e) {
           e.printStackTrace();
         }
       }
     }
   } catch (IOException e) {
     e.printStackTrace();
   }
 }
}

客户端服务器端发送和接受流
不管是客户端Socket处理流或者服务器端获得Socket处理流,不要随便关闭它们获得的输入流和输出流,因为关闭这些流的时候会将该Socket也给关闭了,这是由于流在关闭的时候会释放它所占有的资源,如句柄或端口。
输入流处理
输入流处理主要就是处理来自socket发送的请求信息,不管是客户端还是服务器端都需要先利用getInputstream获得一个socket传输的流。
下面是输入流中最关键的部分就是分析请求的头部,主要是在服务器端
   Socket socket= null;
   BufferedReader netwin= null; //一般在网络中不用这种方式,仅仅一般测试用
try{
     socket= new Socket( "localhost",2222);

     String header= "HTTP/1.0 200 OK\r\n"+
"Server:Apache 7.0\r\n"+
"Content-length:"+107+ "\r\n"+
"Content-type: text/html\r\n\r\n";


//输出流
     OutputStream outfile= new BufferedOutputStream(socket.getOutputStream());
     Writer write= new OutputStreamWriter(outfile);
//输入流
     InputStream inputstream=socket.getInputStream();
     BufferedInputStream in= new BufferedInputStream(inputstream);
     InputStreamReader inr= new InputStreamReader(in);


//对于http请求的需要先判断是否是http协议
//判断请求是否是http协议主要就是处理输入流中的第一行
//第一种处理解析请求头部
     StringBuffer request1= new StringBuffer(100);
while( true)
     {
int c=in.read();
if(c=='\r' || c=='\n' || c==-1)
break;
       request1.append(( char)c);
     }
     String requestHeader1=request1.toString();
if(requestHeader1.indexOf( "HTTP/")!=-1)
       write.write(header);
     write.flush();
     write.close();


//第二种处理解析请求头部
     StringBuffer request2= new StringBuffer(100);
while( true)
     {
int c=in.read();
if(c=='\r' || c=='\n' || c==-1)
break;
       request2.append(( char)c);
     }
//截取第一行每一部分
//一般http请求格式GET /index.html HTTP/1.0
     String requestHeader2=request2.toString();
int firstSpace=requestHeader2.indexOf(' ');
int secondSpace=requestHeader2.indexOf(' ', firstSpace+1);
     String fileName=requestHeader2.substring(firstSpace+1,secondSpace);
if(requestHeader1.indexOf( "HTTP/")!=-1)
     {
       write.write(header);
       write.flush();
       write.close();
     }


//第三种处理解析请求头部
     StringBuffer request3= new StringBuffer(100);
while( true)
     {
int c=in.read();
if(c=='\r' || c=='\n' || c==-1)
break;
       request3.append(( char)c);
     }
//截取第一行每一部分
//一般http请求格式GET /index.html HTTP/1.0
     String requestHeader3=request3.toString();
//使用默认分隔符,包括空白字符,制表符,换行符,回车符,换页符
     StringTokenizer st= new StringTokenizer(requestHeader3);
     String method=st.nextToken();
     String version="";
     String filename=st.nextToken();
     String httpT="";
if(st.hasMoreTokens())
       httpT=st.nextToken();
if(httpT.indexOf( "HTTP/")!=-1)
     {
       write.write(header);
       write.flush();
       write.close();
     }

   } catch(IOException e)
   {
     e.printStackTrace();
   }

输出流处理
在利用http发送数据的时候,每一行都应该由\r\n结束,一般不要使用pringln这种,因为java在linux中换行是以\n结束,windows下换行是以\r\n。 但是在利用http进行请求与响应的过程中,两个都必须每次写入后最后要写入\r\n\r\n,再要将输出流flush以及关闭该输出流。如果不是用http请求一般只需要在每行加入\r\n
不管是客户端还是服务器端要发送流,就必须先getOutputStream来获取一个写入流,用于发送到另一端的Socket中。一般均要放到输出流或者书写器中。
输出流是以字节为单位写的,这样会加快数据的传输速度,便于传输。
书写器是以字符为单位写的,方便写入数据。
基本的输出流写入方式
       socket= new Socket( "localhost",2222);
       OutputStream outs=socket.getOutputStream();
//利用缓冲来
       BufferedOutputStream buffer= new BufferedOutputStream(outs);
       writer= new OutputStreamWriter(buffer);

//在写入的过程中每一行必须要以\r\n结束
       writer.write( "hello");

//这里是一般请求则,只需要加上\r\n即可
       writer.write( "\r\n");
//当是http请求的时候需要这样处理,请求最后加上\r\n
//writer.write("GET /index.html http/1.0 ")
//writer.write("\r\n\r\n")
       writer.flush();
       writer.close();
当是对于http请求进行响应的时候就需要写入MIME首部,且返回文件的时候,该代码实例基本功能是传输客户端请求的页面,并且根据http协议传送首部,错误处理
//这里写入的只是一些小型文件的处理
     InputStream in= new FileInputStream( "f:\\t.txt");
     ByteArrayOutputStream out= new ByteArrayOutputStream();
int b;
while((b=in.read())!=-1)out.write(b);
byte[] data=out.toByteArray();

//下面的是读取大文件处理的方式
//      File file=new File("f:\\t.txt");
//      DataInputStream fis=new DataInputStream(
//          new BufferedInputStream(new FileInputStream(file)));
//      //存放数据
//      byte[] data=new byte[(int)file.length()];
//      fis.readFully(data);//将文件读入到字节数组中
//      fis.close();//直接在输出流中加入该data


//编写MIME首部的格式
     String header= "HTTP/1.0 200 OK\r\n"+
"Server:Apache 7.0\r\n"+
"Content-length:"+data.length+ "\r\n"+
"Content-type: text/html\r\n\r\n";

//开始写入输出流
     socket= new Socket( "localhost",2222);
//利用缓冲来
     OutputStream outfile= new BufferedOutputStream(socket.getOutputStream());
     Writer write= new OutputStreamWriter(outfile);
//这里一般要先判断是否是http协议,
//if(request.indexof("HTTP")!=-1)
//write.write(header);
     write.flush();
     write.close();

//发送文件一般直接用输出流,不要用书写器
     outfile.write(data);
     outfile.flush();
     outfile.close();

//当文件不存在的时候
//这里还是要判断是否是http协议,如果是先要添加MIME首部
       write.write( "HTTP/1.0 404 File Not Found\r\n");
       write.write( "Server:Apache 7.0\r\n");
       write.write( "Content-type:text/html");
       write.write( "\r\n\r\n");

//当不是http协议还要输出显示
       write.write( "<HTML>\r\n");
       write.write( "<HEAD><TITLE>File Not Found</TITLE></HEAD>\r\n");
       write.write( "<BODY>HTTP ERROR 404 :File Not Found\r\n");
       write.write( "</BODY></HTML>\r\n");
       write.flush();
       write.close();