网络协议七层结构:

什么是Socket?

  socket(套接字)是两个程序之间通过双向信道进行数据交换的端,可以理解为接口。使用socket编程也称为网络编程,socket只是接口并不是网络通信协议。

HTTP协议和Socket的区别

  http协议是应用层,其模式是请求-应答,客户端发送请求,服务器端进行响应。传输的数据是原始格式的数据,eg :json、xml、text等数据格式。

  socket不是协议是接口,socket提供TCP/UDP socket 的实例,供java 或者其他语言操作数据的传输,socket是对传输层(TCP/UPD协议)的封装。

Socket通信分为两种

  TCP Socket :使用流传输,提供inputStream 和 outputStream 方法对数据进行流操作。要理解TCP套接字首先要对TCP协议有所理解。

    1)TCP协议是传输层的协议,他的下一层是IP协议(网络层),IP协议在网络数据传输是通过ip寻址,将源地址和目的地址进行连接。TCP协议是在IP协议上多加一层端口寻址,光只通过IP寻址只能定位到主机,tcp通过端口找到对应的应用程序。

    2)TCP 建立连接需要三次握手,将源应用程序和目的应用程序之间搭建一个连接,所以源应用和目的应用程序之间必须是one by one。IP 协议只管数据的传输,不保证数据是否丢失,重复传,顺序是否正确,TCP会对这些问题做一些补偿机制,丢失数据重传,用队列保证数据的顺序。

    3) TCP 缺点:因为每个客户端和服务器端传输数据都要建立连接,三次握手是不传输数据并且有耗时,当有大量短连接的时候并且对数据的正确性要求不高的时候,将会占用带宽。

  UDP Socket:使用数据报文进行传输,创建UDP socket 发送和接收数据报文。

    1)UDP协议同TCP协议一样都是应用层协议,也是通过端口寻址,找到对应的应用程序。

    2)UDP传输数据报文不需要和目的应用程序建立连接,他在数据报文中指定目的主机和目的端口号,发送出的数据自动寻址到对应的主机和端口号。因为不用和目的主机建立连接,所以一个源应用程序可以以广播的形式将数据报文传输给多主机。因为不用建立连接,耗时和带宽占用量都比TCP协议更优秀

    3)UDP缺点:数据有可能丢失,丢失的数据不会重传

java socket 实例

  TCP Socket client

package socket.transmission.tcp;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket; //TCP 套接字 客户端负责发送请求
public class TcpClient {
private static final int BUF_SIZE=32;
/**
* TCP客户端发送一个请求要有三个步骤:
* 1.创建一个socket的实例,创建一个指向server主机ip和端口号的TCP连接
* 2.通过套接字的输入和输出流进行通信
* 3.使用socket close关闭
*/
public static void main(String[] args){
String ip="192.168.197.1";
int port=8080;
try {
// 创建一个socket实例
Socket socket=new Socket(ip,port); // 1 设置TCP SOCKET,初始化目的主机ip和端口号,建立和目的主机的连接,若目的主机没有开启服务,则会弹出server refused
System.out.println("创建一个socket连接");
InputStream inputStream=socket.getInputStream(); // 2 获取回馈服务器的输入流
OutputStream outputStream=socket.getOutputStream(); // 3 将要传输的数据数据写入到输出流中,传输给目的主机
//向socket中写入数据
outputStream.write("this is a word".getBytes()); // 4 传输数据到目的主机
int totalByrecive=0; //到目前为止接收到的数据
byte[] readBuff=new byte[BUF_SIZE];
int lastReadByte; //最后接收的字节
System.out.println("从服务器中接收的数据:");
int receiveMsgSize;
while ((receiveMsgSize=inputStream.read(readBuff))!=-1){ // 5.从回馈服务器中获取数据,
System.out.println(new String(readBuff));
}
socket.close(); //关闭
} catch (IOException e) {
e.printStackTrace();
}
} }

tcp sokect server

package socket.transmission.tcp;

//TCP 服务器端进行接收请求

import sun.java2d.pipe.OutlineTextRenderer;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress; /**
* TCP服务器对客户端发送的请求会进行以下处理
* 1.创建serverSocket实例并且指定本机端口,功能:监听指定端口发送过来的连接
* 2.重复执行:
* 1).调用的serverSocket 的accept() 监听客户端发送过来的请求,并创建socket
* 2).使用socket的inputStream 和 outputStream 进行通讯
* 3).通信完使用socket.close() 方法将连接关闭
*/
public class TcpServer { private static final int BUF_SIZE=32; public static void main(String[] args){
int port=8080;
Socket socket = null;
InputStream inputStream = null;
OutputStream outputStream = null;
try {
ServerSocket serverSocket=new ServerSocket(port);//创建一个socket实例用于监听客户端发送的连接,指定本服务器的端口号
System.out.println("创建serverSocket 实例");
int reviceMsgSize; // 接收msg的大小
byte[] receiveBuf=new byte[BUF_SIZE]; //创建一个信息接收的缓冲区
System.out.println("开始处理接收的数据");
while (true) {
socket = serverSocket.accept(); //接收客户端的连接,每接收一个数据都会创建一个连接,当没有数据的接收的时候会阻塞
SocketAddress socketAddress = socket.getRemoteSocketAddress(); //
System.out.println("访问的地址:" + socketAddress);
inputStream = socket.getInputStream();
outputStream = socket.getOutputStream();
while ((reviceMsgSize = inputStream.read(receiveBuf)) != -1) {
System.out.println(new String(receiveBuf));
outputStream.write("aaaaa".getBytes(), 0, 4);
}
outputStream.flush();
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(socket!=null){
socket.close();
}
if(inputStream!=null){
inputStream.close();
}
if(outputStream!=null){
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
} }

UDP Socket client

package socket.transmission.udp;

import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.*; //UDP 套接字传输的是数据报文 /**
* UDP 客户端发送数据报文的步骤:
* 1.创建UPD 套接字 DataGramSocket ,使用UDP协议通信是不需要和服务器端创建的连接的,UPD协议只是在IP协议上
* 多加了一层端口寻址,设置超时
* 2.创建发送的数据报文实例DataGramPacket,若是单播的则要指明目的端的ip地址和port,IP地址通过创建InetAddress 的实例
* 3.创建接收数据报文实例DataGramPacket ,指定接收数据的缓冲区
* 4.调用socket的send方法将数据报文发送出去
* 5.循环接收数据报文,当数据报文丢失的时候,发起重试。否则设置响应标志位true,将数据打印
*/
public class UdpClient {
/**
* 当客户端发送给server端信息,收到回馈信息的时候,通过read读取数据,当没有数据返回(数据丢失)
* read 方法会发生阻塞,若没有设置超时重发,则程序会一直阻塞
*/
private static final int TIME_OUT=2000; //设置超时重发时间 private static final int MAX_RENTRY=3; // 设置最大重试次数 public static void main(String[] args) throws IOException {
try {
int serverPort=8080; // 指定
byte[] sendMsg="this is a test".getBytes();
DatagramSocket socket=new DatagramSocket(); //创建一个数据报文
socket.setSoTimeout(TIME_OUT); //设置read阻塞超时时间
byte[] ipByte={10,1,1,100};
/**
* "10.1.1.100".getbytes()的方式不能正确的创建server端,调用InetAddress.getByAddress() 方法将会做两个长度判断,IPV4 的入参长度要==4
* IPV6 的长度要== 16 而通过10.1.1.100 getbytes的方式获取的长度是10 抛出违法的长度
*/
InetAddress inetAddress= InetAddress.getByAddress(ipByte); //创建server主机的ip地址
DatagramPacket sendPacket=new DatagramPacket(sendMsg,sendMsg.length,inetAddress,8080); //发送的数据报文
DatagramPacket receivePacket=new DatagramPacket(new byte[sendMsg.length],sendMsg.length); //接收的数据报文
int tryTimes=0; //数据报文可能丢失,设置重试计数器
Boolean receiveResponse=false;
socket.send(sendPacket); //将数据报文发送出去
do{
try {
socket.receive(receivePacket); //尝试去循环接收数据报文
if (!receivePacket.getAddress().equals(inetAddress)) { //检查回馈过来的数据报文
throw new IOException("未知的Server端数据报文");
}
receiveResponse=true;
}catch (InterruptedIOException e){ //数据报文中断异常
tryTimes++;
System.out.println("超时还有"+(MAX_RENTRY-tryTimes)+"次重试机会");
}
}while(!receiveResponse&&(tryTimes<MAX_RENTRY));
if(receiveResponse){
System.out.println("从服务器端获取的数据:"+new String(receivePacket.getData()));
}else{
System.out.println("没有获取到数据");
}
socket.close(); //关闭套接字
} catch (SocketException e) {
e.printStackTrace();
}
}
}

UPD Soceket server

package socket.transmission.udp;

import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.*; //UDP 套接字接收客户端的数据报文
public class UdpServer {
private static final int ECHO_MAX=255; //设置缓冲区的长度 public static void main(String[] args) {
try {
DatagramSocket datagramSocket=new DatagramSocket(8080);
DatagramPacket reveiveMsg=new DatagramPacket(new byte[ECHO_MAX],ECHO_MAX);
while(true){
datagramSocket.receive(reveiveMsg);
System.out.println("从客户端接收的来数据:"+new String(reveiveMsg.getData()));
//在服务器端将发送的信息修改
byte[] newData="啦啦啦啦".getBytes();
// reveiveMsg=new DatagramPacket(newData,newData.length);
//将转化后的数据发送
datagramSocket.send(reveiveMsg);
/**
* 重置接收包的长度,因为接收数据的时候已经接收包的长度设置为接收信息的长度,当下次再接收数据的时候,
* 新数据的长度大于上一次数据的长度时,多出的数据将被截断,所以要重置接收包缓冲区的长度
*/
reveiveMsg.setLength(ECHO_MAX);
}
} catch (UnknownHostException e) {
e.printStackTrace();
}catch (SocketException se){
se.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} }
}

上面的代码还有一些未补足的:要在finally 中将所有的流关闭。

TCP/UDP套接字 java socket编程实例的更多相关文章

  1. java套接字(socket)实例

    客户端socket 流程: 1.连接远程主机 2.发送数据 3.接收数据 4.关闭流与socket连接 实例: import java.io.*; import java.net.Socket; im ...

  2. windows套接字阻塞模式编程实例

    一.阻塞模式套接字服务端和客户端的运行流程如下: 1.1 服务器运行过程如下: 1.服务器启动后,等待客户端的连接请求.2.当收到客户端的请求后,在界面上显示该客户端的IP地址和端口,以及“Hello ...

  3. Day09: socket网络编程-OSI七层协议,tcp/udp套接字,tcp粘包问题,socketserver

    今日内容:socket网络编程    1.OSI七层协议    2.基于tcp协议的套接字通信    3.模拟ssh远程执行命令    4.tcp的粘包问题及解决方案    5.基于udp协议的套接字 ...

  4. java socket编程实例代码

    1.所谓socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄.应用程序通常通过"套接字"向网络发出请求或者应答网络请求. 两性话题 两性 ...

  5. TCP和UDP套接字编程 (java实现)

    在了解网络编程之前,我们先了解一下什么叫套接字 套接字即指同一台主机内应用层和运输层之间的接口 由于这个套接字是建立在网络上建立网络应用的可编程接口 因此也将套接字称为应用程序和网络之间的应用程序编程 ...

  6. Java 网络编程(五) 使用TCP/IP的套接字(Socket)进行通信

    链接地址:http://www.cnblogs.com/mengdd/archive/2013/03/10/2952616.html 使用TCP/IP的套接字(Socket)进行通信 套接字Socke ...

  7. java基础----->TCP和UDP套接字编程

    这里简单的总结一下TCP和UDP编程的写法,另外涉及到HttpUrlConnection的用法 . TCP套接字 一.项目的流程如下说明: .客户输入一行字符,通过其套接字发送到服务器. .服务器从其 ...

  8. 【Python网络编程】利用Python进行TCP、UDP套接字编程

    之前实现了Java版本的TCP和UDP套接字编程的例子,于是决定结合Python的学习做一个Python版本的套接字编程实验. 流程如下: 1.一台客户机从其标准输入(键盘)读入一行字符,并通过其套接 ...

  9. 【Java】Java网络编程菜鸟进阶:TCP和套接字入门

    Java网络编程菜鸟进阶:TCP和套接字入门 JDK 提供了对 TCP(Transmission Control Protocol,传输控制协议)和 UDP(User Datagram Protoco ...

随机推荐

  1. Java 文件路径的读取

    记得在操作系统中了解到文件读取有两种方式,当然这在各编程语言中也是通用的,所以java路径也分,相对和绝对路径. 绝对路径 绝对路径URI ,听着和URL非常相似.那我们就来看看吧. URI(Unif ...

  2. maximize_window fullscreen_window minimize_window

    # Licensed to the Software Freedom Conservancy (SFC) under one# or more contributor license agreemen ...

  3. ASP.NET Web Pages (Razor) API Quick Reference

    ASP.NET Web Pages (Razor) API Quick Reference By Tom FitzMacken|February 10, 2014 Print This page co ...

  4. Tju 4119. HDFS

    4119.   HDFS Time Limit: 5.0 Seconds   Memory Limit: 5000KTotal Runs: 225   Accepted Runs: 77 In HDF ...

  5. HDU3394 Railway —— 点双联通分量 + 桥(割边)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3394 Railway Time Limit: 2000/1000 MS (Java/Others)   ...

  6. 关于intent传递对象后是传递的对象的地址还是对象的拷贝?

    var intent = Intent(activity,SingleColorControlActivity::class.java); var bundle = Bundle()// bundle ...

  7. facebook Presto SQL分析引擎——本质上和spark无异,分解stage,task,MR计算

    Presto 是由 Facebook 开源的大数据分布式 SQL 查询引擎,适用于交互式分析查询,可支持众多的数据源,包括 HDFS,RDBMS,KAFKA 等,而且提供了非常友好的接口开发数据源连接 ...

  8. ssh 无密码互通

    节点n1 n2 n3 互通 第一步:n1->n2互通 admin@n1 > ssh-keygen -d

  9. JSP指令--include指令(静态包含)

    转自:https://blog.csdn.net/chentiefeng521/article/details/51802319 include指令         include指令是文件加载指令, ...

  10. TS数据流PAT和PMT分析(转载)

    转自:http://www.cnblogs.com/hjj801006/p/3837435.html TS流,是基于packet的位流格式,每个packet是188个字节或者204个字 节(一般是18 ...