网络编程

来源:互联网 发布:windows phone7.8 编辑:程序博客网 时间:2024/05/22 12:10



    OSI(Open System Interconnection 开放系统互连)参考模型
    TCP/IP 参考模型

这里写图片描述

    七层描述


    1. 物理层:主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流(就是由1、0转化为电流强弱来进行传输,到达目的地后再转化为1、0,也就是我们常说的数模转换与模数转换)。这一层的数据叫做比特。
    2. 数据链路层:主要将从物理层接收的数据进行MAC地址(网卡的地址)的封装与解封装。常把这一层的数据叫做帧。在这一层工作的设备是交换机,数据通过交换机来传输。
    3. 网络层:主要将下层接收到的数据进行IP地址(例,192.168.0.1)的封装与解封装。在这一层工作的设备是路由器,常把这一层的数据叫做数据包。
    4. 传输层:定义了一些传输数据的协议和端口号(WWW端口号80等),如:TCP(传输控制协议,传输效率低,可靠性强,用于传输可靠性要求高,数据量大的数据),UDP(用户数据报协议,与TCP特性恰恰相反,用于传输可靠性要求不高,数据量小的数据,如QQ聊天数据就是通过这种方式传输的)。主要是将从下层接收的数据进行分段和传输,到达目的地址后再进行重组。常常把这一层叫做段。
    5. 会话层:通过传输层(端口号:传输端口与接收端口)建立数据传输的通路。主要在你的系统之间发起会话或者接收会话请求(设备之间需要互相认识可以是IP也可以是MAC或者是主机名)。
    6. 表示层:主要是进行对接收的数据进行解释,加密与解密、压缩与解压缩等(也就是把计算机能够识别的东西转换成人能够识别的东西(如图片、声音等)。
    7. 应用层:主要是一些终端的应用,比如说FTP(各种文件下载)、WEB(IE浏览)、QQ之类的(可以把它理解成我们在电脑屏幕上可以看到的东西,就是终端应用)。


    P.S.
    1、每个网卡的MAC地址都是全球唯一的。
    2、路由器实现将数据包发送到指定的地点。
    3、应用软件之间通信的过程就是层与层之间封包、解封包的过程。





    4、OSI参考模型虽然设计精细,但过于麻烦,效率不高,因此才产生了简化版的TCP/IP参考模型。




  网络通讯要素


    1. IP地址:InetAddress


        网络中设备的标识。
        不易记忆,可用主机名。
        本地回环地址:127.0.0.1 主机名:localhost。
InetAddress类


特点:无构造函数,可通过getLocalHost()方法获取InetAddress对象,此方法是静态的,返回本类对象。 
InetAddress i = InetAddress.getLocalHost();
方法: 
(1)static InetAddress getByName(String host):获取指定主机的IP和主机名。(最好用ip地址去获取,主机名需要解析) 
(2)static InetAddress[] getAllByName(String host):在给定主机名的情况下,根据系统上配置的名称服务返回IP地址所组成的数组。返回对象不唯一时,用此方法。 
(3)String getHostAddress():返回IP地址字符串文本形式,以IP地址为主。 
(4)String getHostName():返回IP地址主机名。
如何获取任意一台主机的IP地址对象: 
(1)功能:返回InetAddress对象 
(2)对于任意主机,需要指定传入主机名的参数


数据传输用到传输协议
传输协议
        
        通讯的规则。
        常见协议:UDP、TCP。


    UDP---->必须要掌握的
    将数据及源和目的封装成数据包中,不需要建立连接。
    每个数据报的大小在限制在64k内。
    因无连接,是不可靠协议。
    不需要建立连接,速度快。


    应用案例:QQ、FeiQ聊天、在线视频用的都是UDP传输协议。


    TCP
    建立连接,形成传输数据的通道。
    在连接中进行大数据量传输。
    通过三次握手完成连接,是可靠协议。
    必须建立连接,效率会稍低。


    应用案例:FTP,File Transfer Protocol(文件传输协议)。


定义一个udp发送端。将一段文字发送出去
那么就要用到 Socket:UDP协议-发送端&接收端(插座)
    Socket就是为网络服务提供的一种机制。
    通信的两端都有Socket。
    网络通信其实就是Socket间的通信。
    数据在两个Socket间通过IO传输。


udp的Socket服务用<DatagramSocket(用来发送和接收数据报包的套接字)与DatagramPacket(数据报包用来实现无链接包投递服务)>建立


DatagramSocket(用来发送和接收数据报包的套接字)与DatagramPacket(数据报包)。
    建立发送端,接收端。
    建立数据包。
    调用Socket的发送接收方法。
    关闭Socket。
    发送端与接收端是两个独立的运行程序。


步骤:
1,建立updsocket服务。
2,提供数据,并将数据封装到数据包中。
3,通过socket服务的发送功能,将数据包发出去。
4,关闭资源。
//通过udp将一段数据发送出去
import java.net.*;
class  UdpSend
{
public static void main(String[] args) throws Exception
{
//1,创建udp服务。通过DatagramSocket对象。
DatagramSocket ds = new DatagramSocket(8888);


//2,确定数据,并封装成数据包。DatagramPacket(byte[] buf, int length, InetAddress address, int port) 


byte[] buf = "udp ge men lai le ".getBytes();//字符串转换字节数组,编码多了就记住了
DatagramPacket dp = 
new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.254"),10000);//定义了数组,其长度,发送端IP.10000为端口,发送到此端口的接受端


//3,通过socket服务,将已有的数据包发送出去。通过send方法。
ds.send(dp);


//4,关闭资源。


ds.close();


}
}


定义udp的接收端。
步骤:
1,定义udpsocket服务。通常会监听一个端口。其实就是给这个接收网络应用程序定义数字标识。
方便于明确哪些数据过来该应用程序可以处理。


2,定义一个数据包,因为要存储接收到的字节数据。
因为数据包对象中有更多功能可以提取字节数据中的不同数据信息。
3,通过socket服务的receive方法将收到的数据存入已定义好的数据包中。
4,通过数据包对象的特有功能。将这些不同的数据取出。打印在控制台上。
5,关闭资源。




import java.net.*;
class  UdpRece
{
public static void main(String[] args) throws Exception
{
//1,创建udp socket,建立端点。
DatagramSocket ds = new DatagramSocket(10000);//接收与发送端端口相同的数据,
while(true)
{
//2,定义数据包。用于存储数据。
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,buf.length);


//3,通过服务的receive方法将收到数据存入数据包中。
ds.receive(dp);//阻塞式方法。



//4,通过数据包的方法获取其中的数据。
String ip = dp.getAddress().getHostAddress();


String data = new String(dp.getData(),0,dp.getLength());


int port = dp.getPort();//获取端口


System.out.println(ip+"::"+data+"::"+port);


}
//5,关闭资源
//ds.close();


}
}


 由于UDP协议传输数据,只管发送数据,而不管接收端是否能够接收到数据。因此,应该首先启动接收端程序,再启动发送端程序。




使用UDP编写一个聊天程序。
有收数据的部分,和发数据的部分。
这两部分需要同时执行。
那就需要用到多线程技术。
一个线程控制收,一个线程控制发。


因为收和发动作是不一致的,所以要定义两个run方法。
而且这两个方法要封装到不同的类中。


import java.io.*;
import java.net.*;
class Send implements Runnable//使用Runnable接口创建线程
{
private DatagramSocket ds;
public 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,InetAddress.getByName("192.168.1.255"),10002);


ds.send(dp);


if("886".equals(line))
break;
}
}
catch (Exception e)
{
throw new RuntimeException("发送端失败");
}
}
}


class Rece implements Runnable//Runnable接口,创建线程第二方法
{


private DatagramSocket ds;
public Rece(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();


String data = new String(dp.getData(),0,dp.getLength());


if("886".equals(data))
{
System.out.println(ip+"....离开聊天室");
break;
}




System.out.println(ip+":"+data);
}
}
catch (Exception e)
{
throw new RuntimeException("接收端失败");
}
}
}




class  ChatDemo
{
public static void main(String[] args) throws Exception
{
DatagramSocket sendSocket = new DatagramSocket();
DatagramSocket receSocket = new DatagramSocket(10002);端口


new Thread(new Send(sendSocket)).start();//线程开始
new Thread(new Rece(receSocket)).start();


}
}






TCP传输
Socket和ServerSocket:
建立客户端和服务端,建立链接后通过Socket中的IO流进行数据传输,客户端对应的对象是Socket。服务端对应的对象是ServerSocket。
关闭socket
同样--客户端和服务端是两个独立的应用的程序,


创建socket服务,指定要链接的主机和端口
import java.io.*;
import java.net.*;
class  TcpClient
{
public static void main(String[] args) throws Exception 
{
//创建客户端的socket服务。指定目的主机和端口
Socket s = new Socket("192.168.1.254",10003);

//为了发送数据,应该获取socket流中的输出流。
OutputStream out = s.getOutputStream();


out.write("tcp ge men lai le ".getBytes());




s.close();
}
}


服务端:
1,建立服务端的socket服务。ServerSocket();
并监听一个端口。
2,获取连接过来的客户端对象。
通过ServerSokcet的 accept方法。没有连接就会等,所以这个方法阻塞式的。
3,客户端如果发过来数据,那么服务端要使用对应的客户端对象,并获取到该客户端对象的读取流来读取发过来的数据。
并打印在控制台。


4,关闭服务端。(可选)
import java.io.*;
import java.net.*;
class  TcpServer
{
public static void main(String[] args) throws Exception
{
//建立服务端socket服务。并监听一个端口。
ServerSocket ss = new ServerSocket(10003);


//通过accept方法获取连接过来的客户端对象。
while(true)
{
Socket s = ss.accept();//通过accept()获取已连接的客户端对象,并通过该对象与客户端通过IO流进行数据传输


String ip = s.getInetAddress().getHostAddress();
System.out.println(ip+".....connected");


//获取客户端发送过来的数据,那么要使用客户端对象的读取流来读取数据。InputStream
InputStream in = s.getInputStream();

byte[] buf = new byte[1024];
int len = in.read(buf);


System.out.println(new String(buf,0,len));


s.close();//关闭客户端.
}
//ss.close();//可选
}
}




客户端(Client)首先与服务端(Server)建立连接,形成通道(其实就是IO流),然后,数据就可以在通道之间进行传输,并且单个Server端可以同时与多个Client端建立连接。
客户端需要明确服务器的ip地址以及端口,这样才可以去试着建立连接,如果连接失败,会出现异常。
    连接成功,说明客户端与服务端建立了通道,那么通过IO流就可以进行数据的传输,而Socket对象已经提供了输入流和输出流对象,通过getInputStream(),getOutputStream()获取即可。
    与服务端通讯结束后,关闭Socket。


我们可以用tcp的传输的客户端和服务端进行互访。给服务端数据,服务端返回给给客户反馈


客户端:
1,建立socket服务。指定要连接主机和端口。
2,获取socket流中的输出流。将数据写到该流中。通过网络发送给服务端。
3,获取socket流中的输入流,将服务端反馈的数据获取到,并打印。
4,关闭客户端资源。


class TcpClient2 
{
public static void main(String[] args)throws Exception 
{
Socket s = new Socket("192.168.1.254",10000);//指定的主机和端口,

OutputStream out = s.getOutputStream();//输出流


out.write("服务端,你好".getBytes());



InputStream in = s.getInputStream();//读


byte[] buf = new byte[1024];


int len = in.read(buf);


System.out.println(new String(buf,0,len));


s.close();
}
}


//服务端
class TcpServer2
{
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");//提示已经创立链接
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();//输出流,进行反馈用




Thread.sleep(10000);
out.write("哥们收到,你也好".getBytes());


s.close();


ss.close();
}
}




演示客户端和服务端。


1,
客户端:浏览器 (telnet)
服务端:自定义。


2,
客户端:浏览器。
服务端:Tomcat服务器。封装了serversocket


3,
客户端:自定义。(图形界面)
服务端:Tomcat服务器。


最常见的客户端:浏览器,IE/chrome。
    最常见的服务端:服务器,Tomcat。




HTTP服务端发回的应答消息:


        (应答行,HTTP的协议版本:1.1;应答状态码:200;应答状态描述信息:OK。)
        HTTP/1.1 200 OK
        (应答消息属性信息,属性名:属性值。)
        Server: Apache-Coyote/1.1
        Accept-Ranges: bytes
        ETag: W/"211-1433908112666"
        Last-Modified: Wed, 10 Jun 2015 03:48:32 GMT
        Content-Type: text/html
        Content-Length: 211
        Date: Wed, 10 Jun 2015 03:52:16 GMT
        Connection: close


URL:统一资源定位符,也就是说根据URL能够定位到网络上的某个资源,它是指向互联网“资源”的指针。
    每个URL都是URI,但不一定每个URI都是URL。这是因为URI还包括一个子类,即统一资源名称(URN),它命名资源但不指定如何定位资源


String getFile() 
          获取此 URL 的文件名。 
 String getHost() 
          获取此 URL 的主机名(如果适用)。 
 String getPath() 
          获取此 URL 的路径部分。 
 int getPort() 
          获取此 URL 的端口号。 
 String getProtocol() 
          获取此 URL 的协议名称。 
 String getQuery() 
          获取此 URL 的查询部 
注:一般输入网址,是不带端口号的,此时可进行获取,通过获取网址返回的port,若port为-1,则分配一个默认的80端口,如 
int port = getPort(); 
if(port == -1) 
port = 80;


URLConnection:带着协议封装


方法:


URLConnection openConnection();//用URL调用此方法,返回一个 URLConnection 对象,它表示到 URL 所引用的远程对象的连接。
InputStream getInputStream();//获取输入流
OutputStream getOutputStream();//获取输出流 





0 0
原创粉丝点击