TCP/IP,HTTP,SOCKET详解

来源:互联网 发布:手机改不了mac地址 编辑:程序博客网 时间:2024/05/21 17:44

TCP/IP由四个层次组成:网络接口层网络层传输层应用层

OSI中的层

功能

TCP/IP协议族

应用层

文件传输,电子邮件,文件服务,虚拟终端

TFTPHTTPSNMPFTPSMTPDNSTelnet 等等

表示层

数据格式化,代码转换,数据加密

没有协议

会话层

解除或建立与别的接点的联系

没有协议

传输层

提供端对端的接口

TCPUDP

网络层

数据包选择路由

IPICMPOSPFEIGRPIGMP,RIP

数据链路层

传输有地址的帧以及错误检测功能

SLIPCSLIPPPPMTUARPRARP

物理层

以二进制数据形式在物理媒体上传输数据

ISO2110IEEE802IEEE802.2

1.IP

  IP层接收由更低层(网络接口层例如以太网设备驱动程序)发来的数据包,并把该数据包发送到更高层---TCP或UDP层;相反,IP层也把从TCP或UDP层接收来的数据包传送到更低层。IP数据包是不可靠的,因为IP并没有做任何事情来确认数据包是按顺序发送的或者没有被破坏。IP数据包中含有发送它的主机的地址(源地址)和接收它的主机的地址(目的地址)。   高层的TCP和UDP服务在接收数据包时,通常假设包中的源地址是有效的。也可以这样说,IP地址形成了许多服务的认证基础,这些服务相信数据包是从一个有效的主机发送来的。IP确认包含一个选项,叫作IP source routing,可以用来指定一条源地址和目的地址之间的直接路径。对于一些TCP和UDP的服务来说,使用了该选项的IP包好像是从路径上的最后一个系统传递过来的,而不是来自于它的真实地点。这个选项是为了测试而存在的,说明了它可以被用来欺骗系统来进行平常是被禁止的连接。那么,许多依靠IP源地址做确认的服务将产生问题并且会被非法入侵。 

2.TCP

  TCP是面向连接的通信协议,通过三次握手建立连接,通讯完成时要拆除连接,由于TCP是面向连接的所以只能用于点对点的通讯。   TCP提供的是一种可靠的数据流服务,采用“带重传的肯定确认”技术来实现传输的可靠性。TCP还采用一种称为“滑动窗口”的方式进行流量控制,所谓窗口实际表示接收能力,用以限制发送方的发送速度。   如果IP数据包中有已经封好的TCP数据包,那么IP将把它们向‘上’传送到TCP层。TCP将包排序并进行错误检查,同时实现虚电路间的连接。TCP数据包中包括序号和确认,所以未按照顺序收到的包可以被排序,而损坏的包可以被重传。   TCP将它的信息送到更高层的应用程序,例如Telnet的服务程序和客户程序。应用程序轮流将信息送回TCP层,TCP层便将它们向下传送到IP层,设备驱动程序和物理介质,最后到接收方。   面向连接的服务(例如Telnet、FTP、rlogin、X Windows和SMTP)需要高度的可靠性,所以它们使用了TCP。DNS在某些情况下使用TCP(发送和接收域名数据库),但使用UDP传送有关单个主机的信息。 

3.UDP

UDP是面向无连接的通讯协议,UDP数据包括目的端口号和源端口号信息,由于通讯不需要连接,所以可以实现广播发送。   UDP通讯时不需要接收方确认,属于不可靠的传输,可能会出丢包现象,实际应用中要求在程序员编程验证。   UDP与TCP位于同一层,但它不管数据包的顺序、错误或重发。因此,UDP不被应用于那些使用虚电路的面向连接的服务,UDP主要用于那些面向查询---应答的服务,例如NFS。相对于FTP或Telnet,这些服务需要交换的信息量较小。使用UDP的服务包括NTP(网络时间协议)和DNS(DNS也使用TCP)。   欺骗UDP包比欺骗TCP包更容易,因为UDP没有建立初始化连接(也可以称为握手)(因为在两个系统间没有虚电路),也就是说,与UDP相关的服务面临着更大的危险。

建立起一个TCP连接需要经过“三次握手”:

第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;

第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;

第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。

TCP协议四次握手断开连接协议 

由于TCP连接是全双工的因此每个方向都必须单独进行关闭。这个原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭而另一方执行被动关闭。 

1客户端A发送一个FIN用来关闭客户A到服务器B的数据传送(报文段4)。 

 2服务器B收到这个FIN它发回一个ACK确认序号为收到的序号加1(报文段5)。和SYN一样一个FIN将占用一个序号。 

3服务器B关闭与客户端A的连接发送一个FIN给客户端A(报文段6)。 

4 客户端A发回ACK报文确认并将确认序号设置为收到序号加1(报文段

JAVA TCP通信:
TCP服务器端代码:

try { Boolean endFlag = false;

ServerSocket ss = new ServerSocket(12345);

while (!endFlag) {

// 等待客户端连接

Socket s = ss.accept();

BufferedReader input = new BufferedReader(newInputStreamReader(s.getInputStream()));

//注意第二个参数据为true将会自动flush,否则需要需要手动操作output.flush()

PrintWriter output = newPrintWriter(s.getOutputStream(),true);

String message = input.readLine();

Log.d(”Tcp Demo”, “message from Client:”+message);

output.println(”message received!”);

//output.flush();

if(”shutDown”.equals(message)){

endFlag=true;

}

s.close();

}

ss.close();

} catch (UnknownHostException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace(); }

TCP客户端代码:

try { Socket s = new Socket(”localhost”, 12345);

// outgoing stream redirect to socket

OutputStream out = s.getOutputStream();

// 注意第二个参数据为true将会自动flush,否则需要需要手动操作

ut.flush()

PrintWriter output = new PrintWriter(out, true);

output.println(”Hello IdeasAndroid!”);

BufferedReader input = new BufferedReader(newInputStreamReader(s .getInputStream()));

// read line(s) String message = input.readLine();

Log.d(”Tcp Demo”, “message From Server:” + message); s.close();

} catch (UnknownHostException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace(); }

Java UDP通信

UDP服务器端代码:

// UDP服务器监听的端口

Integer port = 12345;

// 接收的字节大小,客户端发送的数据不能超过这个大小

byte[] message = new byte[1024];

try {

// 建立Socket连接

DatagramSocket datagramSocket = new DatagramSocket(port);

DatagramPacket datagramPacket = new DatagramPacket(message, message.length);

try { while (true) {

// 准备接收数据

datagramSocket.receive(datagramPacket);

Log.d(”UDP Demo”, datagramPacket.getAddress() .getHostAddress().toString() + “:” + new String(datagramPacket.getData()));

}

} catch (IOException e) {

e.printStackTrace(); }

} catch (SocketException e) {

e.printStackTrace(); }

UDP客户端代码:

public static void send(String message) {

message = (message == null ? “Hello IdeasAndroid!” : message);

int server_port = 12345;

DatagramSocket s = null;

try { s = new DatagramSocket();

} catch (SocketException e) {

e.printStackTrace();

}

InetAddress local = null;

try {

// 换成服务器端IP

local = InetAddress.getByName(”localhost”);

} catch (UnknownHostException e) {

e.printStackTrace();

}

int msg_length = message.length();

byte[] messagemessageByte = message.getBytes();

DatagramPacket p = new DatagramPacket(messageByte, msg_length, local, server_port);

try { s.send(p); } catch (IOException e) {

e.printStackTrace(); }

}

HTTP协议

HTTP工作在TCP/IP协议体系中的TCP协议上。   客户机和服务器必须都支持 HTTP,才能在万维网上发送和接收 HTML 文档并进行交互。 

(如需更多了解:http://baike.baidu.com/view/70545.htm

1)在HTTP 1.0中,客户端的每次请求都要求建立一次单独的连接,在处理完本次请求后,就自动释放连接。

2)在HTTP 1.1中则可以在一次连接中处理多个请求,并且多个请求可以重叠进行,不需要等待一个请求结束后再发送下一个请求。

由于HTTP在每次请求结束后都会主动释放连接,因此HTTP连接是一种“短连接”,要保持客户端程序的在线状态,需要不断地向服务器发起连接请求。通常的做法是即时不需要获得任何数据,客户端也保持每隔一段固定的时间向服务器发送一次“保持连接”的请求,服务器在收到该请求后对客户端进行回复,表明知道客户端“在线”。若服务器长时间无法收到客户端的请求,则认为客户端“下线”,若客户端长时间无法收到服务器的回复,则认为网络已经断开

SOCKET

建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket ,另一个运行于服务器端,称为ServerSocket 。

套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。

服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。

客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。

连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式建立连接。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。

参考文献

【1】http://baike.baidu.com/view/70545.htm

【2】http://www.cnblogs.com/jiangshiyong/archive/2012/08/26/2657811.html

 

原创粉丝点击