http://www.cnblogs.com/IPrograming/archive/2012/10/15/CSharp_Socket_4.html

http://www.cnblogs.com/dolphinX/p/3460545.html

一、TCP和UDP的区别和联系

1.五层协议体系结构和OSI七层的体系结构

2.五层协议体系结构

  2.1应用层(超文本传输协议)(文件传输)(远程登录)(网络管理)(域名系统)HTTP/TFTP/TELNET/SNMP/DNS

    如何通过应用进程间的交互来完成特定网络应用,是应用进程间的通信和交互规则。

  2.2运输层

    负责向两台主机之间提供通用的数据传输服务,应用层利用这一层的传输服务,传输应用层的报文。

  2.3网络层(Internet协议)(控制信息协议)(地址/反地址解析协议)IP/ICMP/ARP/RARP

    负责为分组交换网上的不同主机提供通信服务。把运输层产生的报文段和用户数据报,封装成分组和包的形式进行传送。

    另外,使源主机运输层所传下来的分组,能够通过网络中路由器找到合适的分组。

  2.4数据链路层

    链路是指节点间的连接,它主要把网络层交下来的分组和包或者是IP数据报封装成帧,在节点之间进行传播。

  2.5物理层

    提供物理媒体,传输bit流。

3.运输层中的UDP和TCP和Socket

  3.1TCP

    ①三次握手

    1.主机A通过向主机B发送一个含有同步序列号的标志位的数据段给主机B,向主机B请求简历连接,通过这个数据段,

主机A告诉主机B两件事:我要和你通信;你可以用哪个序列号作为起始数据段来回应我。

    2.主机B收到主机A的请求后,有一个带有去人应答(ACK)和同步序列号(SYN)标志

位的数据段响应主机A,也告诉主机A两件事:我已经收到你的请求了,你可以传输数据了;你要用哪个序列号作为起始数据段来回应我

    3.主机A收到这个数据段后,再发送一个确认应答,确认已收到主机B的数据段;并开始传输实际数据。

    ②三次握手的特点

    没有应用层的数据,SYN这个标志位只有在TCP建立连接时才会被置1,握手完成后SYN标志位被职位0;

    ③四次挥手

    1.当主机A完成数据传输后,将控制位FIN置1,提出停止TCP连接请求

    2.主机B收到FIN后对其作出响应,确认这一方向的TCP连接将关闭,将ACK置1

    3.由B端在提出反方向的关闭请求,将FIN置1(关闭A端,否则处于半关闭状态)

    4.主机A对主机B的请求进行确认,将ACK置1,双方向的连接关闭。

    ④刷一波,这些标识们

    名词解释
    ACK  TCP报头的控制位之一,对数据进行确认.确认由目的端发出,用它来告诉发送端这个序列号之前的数据段
  都收到了.比如,确认号为X,则表示前X-1个数据段都收到了,只有当ACK=1时,确认号才有效,当ACK=0时,确认号无效,这时  会要求重传数据,保证数据的完整性.
    SYN  同步序列号,TCP建立连接时将这个位置1
    FIN  发送端完成发送任务位,当TCP完成数据传输需要断开时,提出断开连接的一方将这位置1
    TCP的包头结构:
  源端口 16位
  目标端口 16位
  序列号 32位
  回应序号 32位
  TCP头长度 4位
  reserved 6位
  控制代码 6位
  窗口大小 16位
  偏移量 16位
  校验和 16位
  选项  32位(可选)
  这样我们得出了TCP包头的最小长度,为20字节。

  • 消息确认(Message Acknowledgement):当接收端TCP成功接收到TCP报文段之后,会在一个短暂的时间间隔内(并不是在成功接收到报文的那一刻),向发送端发送一个表明该报文段已经被成功接收确认消息(Acknowledgement);
  • 超时重传:发 送端具有一个存储报文段的缓冲区(Buffer),我们一般称为发送端窗口(Sender Window),用于存放已经发送但是尚未接受到确认的报文段。如果接收到确认,会将相应的报文段从发送端窗口中移除。如果在一定的超时时限内没有接收到 确认消息,会认为相应的报文段发送失败,此时发送端TCP会从发送端窗口中提取相应的报文段进行重新发送。

  3.2UDP

(1) UDP是一个非连接的协议,传输数据之前源端和终端不建立连接,当它想传送时就简单地去抓取来自应用程序的数据,并尽可能快地把它扔到网络上。在发送端,UDP传送数据的速度仅仅是受应用程序生成数据的速度、计算机的能力和传输带宽的限制;在接收端,UDP把每个消息段放在队列中,应用程序每次从队列中读一个消息段。
(2) 由于传输数据不建立连接,因此也就不需要维护连接状态,包括收发状态等,因此一台服务机可同时向多个客户机传输相同的消息。
(3) UDP信息包的标题很短,只有8个字节,相对于TCP的20个字节信息包的额外开销很小。
(4) 吞吐量不受拥挤控制算法的调节,只受应用软件生成数据的速率、传输带宽、源端和终端主机性能的限制。
(5)UDP使用尽最大努力交付,即不保证可靠交付,因此主机不需要维持复杂的链接状态表(这里面有许多参数)。
(6)UDP是面向报文的。发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付给IP层。既不拆分,也不合并,而是保留这些报文的边界,因此,应用程序需要选择合适的报文大小。
我们经常使用“ping”命令来测试两台主机之间TCP/IP通信是否正常,其实“ping”命令的原理就是向对方主机发送UDP数据包,然后对方主机确认收到数据包,如果数据包是否到达的消息及时反馈回来,那么网络就是通的。
UDP的包头结构:
源端口 16位
目的端口 16位
长度 16位
校验和 16位

  

  UDP,并不尝试对IP层产生的错误进行修复,它仅仅简单的扩展了IP协议“尽力而为best effort"的数据报服务,使得数据能在应用程序之间工作,而不是在主机之间工作。因此,使用了UDP协议的应用程序必须为处理报文丢失,顺序混乱等问题做好准备。
  UDP协议会用自己的分组结构封装用户消息,它只增加了4个字段:源端口、目标端口、分组长度和校验和。这样,当IP把分组送达目标主机时,该主机能够拆开UDP分组,根据目标端口找到目标应用程序,然后再把消息发送过去。说到底,UDP仅仅是在IP层之上通过嵌入应用程序的源端口和目标端口,提供了一个“应用程序多路复用”机制。明白了这一点,就可以总结一下UDP的无服务是怎么回事了。

  3.3UDP和TCP的区别

  ①基于连接与无连接(是指传输数据之前)

  ②对系统资源的要求(TCP较多,UDP较少)

  ③UDP程序结构较简单,首部开销只有8个字节,而TCP有20个字节。

  ④流模式与数据报模式,UDP没有拥塞控制,UDP中当网络发生拥塞不会使源主机的速率降低,

多用于实时应用中,如IP电话,实时视频会议等。

  ⑤TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证。

  ⑥每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信。

  ⑦TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道。

  ⑧TCP多用于传输少量数据,UDP多用于传输少量数据

3.4Socket

 ① Socket:只是一个抽象层。用来表示程序已经加入到网络中。

  http://www.cnblogs.com/lwzz/archive/2011/07/03/2096651.html

  

指一旦一个程序中有了一个Socket实例对象,那么这个程序就被加到了网络中,可以和网络中的其他应用程序进行通信。

现在来关注Socket是抽象层这段话。既然Socket是抽象的,那么它肯定有很多不同具体的实现,比如说TCP

为基础的TCPSocket和一UDP为基础的UDPSocket。

  ②TCPSocket

  1.用到了

  线程工具类

 import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket; public class ServerThread implements Runnable{ Socket socket = null;
public ServerThread(Socket socket){
this.socket = socket;
}
@Override
public void run() {
InputStream is = null;
InputStreamReader isr = null;
BufferedReader br = null;
OutputStream os = null;
PrintWriter pw = null;
//与客户端建立通信,获取输入流,读取客户端提供的信息
try {
is = socket.getInputStream();
isr = new InputStreamReader(is,"UTF-8");
br = new BufferedReader(isr);
String data = null;
while((data = br.readLine())!=null){
System.out.println("我是服务器,客户端提交的信息为:"+data);
socket.shutdownInput();//关闭输入流 //获取输出流,响应客户端的请求
os = socket.getOutputStream();
pw = new PrintWriter(os);
pw.write("服务器端响应成功");
pw.flush();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
//关闭资源和相关socket
try{
if(pw!=null){
pw.close();
}
if(os!=null){
os.close();
}
if(is!=null){
is.close();
}
if(isr!=null){
isr.close();
}
if(br!=null){
br.close();
}
if(socket!=null){
socket.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}

  服务端

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket; public class Server {
public static void main(String[] args){
//创建一个服务器端的Socket,即ServerSocket,绑定需要监听的端口
try {
ServerSocket serverSocket = new ServerSocket(8888);
Socket socket = null;
//记录连接过服务器端客户端数量
int count = 0;
System.out.println("服务期即将启动,等待客户端的连接");
while(true){//循环监听新的客户端的连接
//调用accept()方法监听,等待客户端的连接以获取Socket实例
socket = serverSocket.accept();
//创建新线程
Thread thread = new Thread(new ServerThread(socket));
thread.start();
count++;
System.out.println("服务器端被连接过的次数:"+count); InetAddress address = socket.getInetAddress();
System.out.println("当前客户端IP为:"+address.getHostAddress());
}
//服务器端的连接不用关闭。
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

  客户端

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException; public class Client1 {
public static void main(String[] args) {
try{
Socket socket = new Socket("localhost",8888);
OutputStream os = socket.getOutputStream();
PrintWriter pw = new PrintWriter(os);
pw.write("用户名:jinxueling;密码:123");
pw.flush();
socket.shutdownOutput(); InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is,"UTF-8");
BufferedReader br = new BufferedReader(isr);
String data = null;
while((data = br.readLine())!=null){
System.out.println("我是客户端,服务器端响应的数据为:"+data);
}
socket.close();
}catch (UnknownHostException e) {
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}
}
}

③UDPSocket

  线程工具类

package UDPSocket;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress; public class UDPThread implements Runnable{ DatagramSocket socket = null;
DatagramPacket packet = null;
public UDPThread(DatagramSocket socket,DatagramPacket packet){
this.socket = socket;
this.packet = packet;
}
@Override
public void run() {
String info = null;
InetAddress address = null;
int port = 8800;
byte[] data2 = null;
DatagramPacket packet2 = null;
try{
//打印当前请求socket客户端的请求数据和信息。
info = new String(packet.getData(),0,packet.getLength());
System.out.println("我是服务器,客户端说:"+info);
//封装数据包,响应给当前socket实例的客户端
address = packet.getAddress();
port = packet.getPort();
data2 = "我在响应你".getBytes();
packet2 = new DatagramPacket(data2, data2.length,address,port);
socket.send(packet2);
}catch(Exception e){
e.printStackTrace();
}
}
}

  服务端

package UDPSocket;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException; public class UDPServer {
public static void main(String[] args) throws IOException {
try {
//创建指定端口的DatagramSocket
DatagramSocket socket = new DatagramSocket(8800);
//声明数据报
DatagramPacket packet = null;
//声明字节数组
byte[] data = null;
//服务器响应的连接计数
int count = 0;
System.out.println("服务器启动,等待发送数据");
//等待客户端连接
while(true){
//初始化字节数组容量,指定接收的数据包的大小
data = new byte[1024];
//初始化数据包
packet = new DatagramPacket(data,data.length);
//等待接收来自服务端的数据包
socket.receive(packet);
//到达这一步,socket.receive方法停止阻塞了,说明有客户端在请求了
//给该客户端创建一个独立的线程,并根据接收到的包,给予响应。
Thread thread = new Thread(new UDPThread(socket,packet));
thread.start();
count++;
System.out.println("服务器端被连接过的次数:"+count);
//打印当前的客户端socket的ip
InetAddress address = packet.getAddress();
System.out.println("当前客户端的IP为:"+address.getHostAddress());
}
} catch (SocketException e) {
e.printStackTrace();
}
}
}

  客户端

package UDPSocket;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress; public class UDPClient {
public static void main(String[] args) throws IOException {
//定义服务器的地址,端口号,数据
InetAddress address = InetAddress.getByName("localhost");
int port = 8800;
byte[] data = "用户名:admin;密码:123".getBytes();
//创建数据报
DatagramPacket packet = new DatagramPacket(data,data.length,address,port);
//创建DatagramSocket,实现数据发送和接收
DatagramSocket socket = new DatagramSocket();
//向服务器发送数据报
socket.send(packet); //接收服务器 响应数据
byte[] data2 = new byte[1024];
DatagramPacket packet2 = new DatagramPacket(data2,data2.length);
socket.receive(packet2);
String info = new String(data2,0,packet2.getLength());
System.out.println("我是客户端,服务器说:"+info);
socket.close();
}
}

TCP和UDP并实现socket的简单通信的更多相关文章

  1. Python网络编程02 /基于TCP、UDP协议的socket简单的通信、字符串转bytes类型

    Python网络编程02 /基于TCP.UDP协议的socket简单的通信.字符串转bytes类型 目录 Python网络编程02 /基于TCP.UDP协议的socket简单的通信.字符串转bytes ...

  2. 基于TCP与UDP协议的socket通信

    基于TCP与UDP协议的socket通信 C/S架构与初识socket 在开始socket介绍之前,得先知道一个Client端/服务端架构,也就是 C/S 架构,互联网中处处充满了 C/S 架构(Cl ...

  3. Day28--Python--网络通信协议 tcp与udp下的socket

    昨日内容回顾: 1. CS架构 服务端客户端架构 软件CS架构: 京东,淘宝,QQ,微信,暴风影音,快播 硬件CS架构: 打印机 服务端: 提供服务的 客户端: 享受服务的 BS架构: 浏览器和服务端 ...

  4. socket的简单通信

    ///客户端 package com.ch.day11_myclient; import java.io.BufferedReader;import java.io.IOException;impor ...

  5. 基于TCP 协议的socket 简单通信

    DNS 服务器:域名解析 socket 套接字 : ​ socket 是处于应用层与传输层之间的抽象层,也是一组操作起来非常简单的接口(接受数据),此接口接受数据之后,交由操作系统 为什么存在 soc ...

  6. UNP(一):网络编程角度下的TCP、UDP协议

    此博文是学习UNP(UNIX Network Programming)后的读书笔记,供以后自己翻阅回想知识. TCP.UDP概述 在前面<计算机网络与TCP/IP>栏目下已经介绍过一些关于 ...

  7. 利用TCP协议,实现基于Socket的小聊天程序(初级版)

    TCP TCP (Transmission Control Protocol)属于传输层协议.其中TCP提供IP环境下的数据可靠传输,它提供的服务包括数据流传送.可靠性.有效流控.全双工操作和多路复用 ...

  8. HTTP、TCP、UDP以及SOCKET之间的区别/联系

    一.TCP/IP代表传输控制协议/网际协议,指的是一系列协组. 可分为四个层次:数据链路层.网络层.传输层和应用层. 在网络层:有IP协议.ICMP协议.ARP协议.RARP协议和BOOTP协议. 在 ...

  9. TCP与UDP在socket编程中的区别

    一.TCP与UDP的区别 基于连接与无连接  对系统资源的要求(TCP较多,UDP少)  UDP程序结构较简单  流模式与数据报模式  TCP保证数据正确性,UDP可能丢包  TCP保证数据顺序,UD ...

随机推荐

  1. Qt定时器

    PS: 本案例使用的是Qt 4.8.4版本,不同版本代码可能会有差异. 第一步: // 重写此虚函数(继承自QObject) virtual void timerEvent(QTimerEvent* ...

  2. VS代码自动排版

    1, ctrl+a 2, ctrl+k 3, ctrl+f

  3. Python基础Day7

    七步记忆法: ① 预习(30min) ② 听课 (重点) ③ 课间练习 ④ 下午或者晚上练习(大量练习.重复练习)⑤ 晚上睡觉前的回忆 ⑥ 第二天早晨回顾 ⑦ 每周总结,自己默写方法 一.enumer ...

  4. HTML中使用图像

    插入图像 在页面中插入图像的标记只有一个,就是img标记. 语法为:<img src="图片地址" alt="下载失败时的替换文本" title='提示文 ...

  5. 【转】SENDING KEY VALUE MESSAGES WITH THE KAFKA CONSOLE PRODUCER

    SENDING KEY VALUE MESSAGES WITH THE KAFKA CONSOLE PRODUCER When working with Kafka you might find yo ...

  6. 【Mac】打开配置文件,添加/修改环境变量

    打开文件编辑器: 进入终端,输入open -e .bash_profile或者open -t ~/.bash_profile  打开profile文件 填写配置的环境变量: #示例代码 export ...

  7. js+css 动效+1的效果

    点击数值 +1 的动效 vue data:{ timer: null,plus:''// 次数 } method:{ animate(plus) { var _this = this; clearIn ...

  8. socket.gaierror: [Errno 11001] getaddrinfo failed

  9. Flask+nginx+Gunicorn部署

    当我们开发完Flask项目后是不能直接通过命令启动服务来使用的(扛不住的) Gunicorn 是一个给 UNIX 用的 WSGI HTTP 服务器.这是一个从 Ruby 的 Unicorn 项目移植的 ...

  10. TDOA 之 基站接收数据

    基站主要 接收同步节点发来的同步信号,代码里定义为S信息. 以及标签节点发来的定位信号,代码中定义为T信号. 代码中使用中断以及帧过滤功能,对模块只接收自己关心设定好的信息,通过中断告知上层,而不是长 ...