网络编程:
计算机网络
计算机网络指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统、网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
网络协议组成三要素:
语义:
规定了通信双方为了完成某种目的,需要发出何种控制信息以及基于这个信息需要做出何种行动。
语法:
是用户数据与控制信息的结构与格式,以及数据出现的先后顺序。
时序:
是对事件发生顺序的详细说明。
语义表示要做什么,语法表示要怎么做,时序表示做的顺序。
网络编程概述
Java是Internet 上的语言,它从语言级上提供了对网络应用程序的支持,程序员能够很容易开发常见的网络应用程序。
Java提供的网络类库,可以实现无痛的网络连接,联网的底层细节被隐藏在Java的本机安装系统里,由JVM 进行控制。并且Java 实现了一个跨平台的网络库,程序员面对的是一个统一的网络编程环境。
网络编程的目的:
- 直接或间接地通过网络协议与其它计算机实现数据交换,进行通讯。
网络编程中有两个主要的问题:
- 如何准确地定位网络上一台或多台主机;定位主机上的特定的应用
- 找到主机后如何可靠高效地进行数据
通信双方地址
- IP
- 端口号
一定的规则(即:网络通信协议。有两套参考模型)
- OSI参考模型:模型过于理想化,未能在因特网上进行广泛推广
- TCP/IP参考模型(或TCP/IP协议):事实上的国际标准。
网络通信协议
OSI参考模型 | TCP/IP参考模型 | TCP/IP参考模型各层对应协议 |
应用层 | 应用层 | HTTP、FTP、Telnet、DNS… |
表示层 | ||
会话层 | ||
传输层 | 传输层 | TCP、UDP、… |
网络层 | 网络层 | IP、ICMP、ARP、RARP… |
数据链路层 | 物理+数据链路层 | Link |
物理层 |
- TCP/IP不是一个协议,而是一个协议族的统称
- TCP/IP协议族按照层次由上到下,层层包装。第一层都有相应的协议。
- 数据从上层向下层传输为封装
- 数据从下层向上层传输为解封
IP地址: InetAddress:
唯一的标识Internet 上的计算机(通信实体)
本地回环地址(hostAddress):127.0.0.1主机名(hostName):localhost
IP地址分类方式1:IPV4和IPV6
- IPV4:4个字节组成,4个0-255。大概42亿,30亿都在北美,亚洲4亿。2011年初已经用尽。以点分十进制表示,如192.168.0.1
- IPV6:128位(16个字节),写成8个无符号整数,每个整数用四个十六进制位表示,数之间用冒号(:)分开,如: 3ffe:3201:1401:1280:c8ff:fe4d:db39:1984
IP地址分类方式2:公网地址(万维网使用)和私有地址(局域网使用)。 192.168.开头的就是私有址址,范围即为192.168.0.0--192. 168.255.255,专门为组织机构内部使用
特点:不易记忆
IP地址由两部分组成:
- 网络号
- 主机号
IP地址有两种表示方式:
二进制表示,比如:01110119 10111010 11010011 01011100
点分十进制表示,比如:119.186.211.92
A类地址
1.0.0.0 到126.0.0.0
0.0.0.0 和127.0.0.0保留
B类地址
128.1.0.0到191.254.0.0
128.0.0.0和191.255.0.0保留
C类地址
192.0.1.0 到223.255.254.0
192.0.0.0和223.255.255.0保留
D类地址
224.0.0.0到239.255.255.255用于多点广播
E类地址
240.0.0.0到255.255.255.254保留
255.255.255.255用于广播
子网掩码:
- 解决IP地址不够用的问题
- 标识子网和主机位
端口号
- 端口号标识正在计算机上运行的进程(程序)
- 不同的进程有不同的端口号
- 被规定为一个16 位的整数0~65535。
- 端口分类:
- 公认端口:0~1023。被预先定义的服务通信占用(如:HTTP占用端口80,FTP占用端口21,Telnet占用端口23)
- 注册端口:1024~49151。分配给用户进程或应用程序。(如:Tomcat占用端口8080,MySQL占用端口3306,Oracle占用端口1521等)。
- 动态/私有端口:49152~65535。
- 端口号与IP地址的组合得出一个网络套接字:Socket。
域名
域名(Domain Name),是由一串用点分隔的名字组成的Internet上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位。
如:www.sohu.com
域名可分为不同级别,包括顶级域名、二级域名等。
顶级域名又分为两类:一是国家和地区顶级域名(country code top-level domains,简称nTLDs),目前200多个国家按照ISO3166国家代码分配了顶级域名,例如中国为cn,日本为jp等;二是国际顶级域名(generic top-level domains,简称gTLDs),例如表示工商企业的.com,表示网络提供商的.net,表示非盈利组织的.org等。
二级域名指顶级域名之下的域名
网络配置:
打开“Internet协议版本4(TCP/IPv4)属性”对话框
常用TCP/IP网络命令
- ipconfig:查看网络配置信息
- ping:检查主机的网络连通情况
URL类:
java.net.URL 代表一个统一资源定位符,它是指向互联网“资源”的指针。资源可以是简单的文件或目录,也可以是对更为复杂的对象的引用,例如对数据库或搜索引擎的查询。
分成几个部分:
- 协议
- 主机
- 端口号
URL(Uniform Resource Locator):统一资源定位符,它表示Internet 上某一资源的地址。
它是一种具体的URI,即URL可以用来标识一个资源,而且还指明了如何locate这个资源。
通过URL 我们可以访问Internet 上的各种网络资源,比如最常见的www,ftp 站点。浏览器通过解析给定的URL 可以在网络上查找相应的文件或其他资源。
URL的基本结构由5部分组成:
<传输协议>://<主机名>:<端口号>/<文件名>#片段名?参数列表
例如: http://192.168.1.100:8080/helloworld/index.jsp#a?username=shkstart&password=123
#片段名:即锚点,例如看小说,直接定位到章节
参数列表格式:参数名=参数值&参数名=参数值
为了表示URL,java.net 中实现了类URL。我们可以通过下面的构造器来初始化一个URL 对象:
public URL (String spec):
通过一个表示URL地址的字符串可以构造一个URL对象。
例如:URL url= new URL ("http://www. atguigu.com/");
public URL(URL context, String spec):
通过基URL 和相对URL 构造一个URL 对象。
例如:URL downloadUrl= new URL(url, “download.html")
public URL(String protocol, String host, String file);
例如:new URL("http", "www.atguigu.com", “download. html");
public URL(String protocol, String host, intport, String file);
例如: URL gamelan = new URL("http", "www.atguigu.com", 80, “download.html");
URL类的构造器都声明抛出非运行时异常,必须要对这一异常进行处理,通常是用try-catch 语句进行捕获。
URL网络编程:URL类常用方法
一个URL对象生成后,其属性是不能被改变的,但可以通过它给定的方法来获取这些属性:
public String getProtocol( ) 获取该URL的协议名
public String getHost( ) 获取该URL的主机名
public String getPort( ) 获取该URL的端口号
public String getPath( ) 获取该URL的文件路径
public String getFile( ) 获取该URL的文件名
public String getQuery( ) 获取该URL的查询名
URL类获取网络上指定资源的信息
输出百度首页html脚本
import java.io.*;
import java.net.URL;
public class TestURL{
//输出百度首页html脚本
public static void main(String args[]){
BufferedReader bufferedReader = null;
try {
//通过URL字符串创建URL对象
URL url = new URL("https://www.baidu.com");
//打开URL连接并返回从该连接读入数据的InputStream
InputStream inputStream = url.openStream();
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String oneLineData;
while ((oneLineData = bufferedReader.readLine()) != null){
System.out.println(oneLineData);
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(bufferedReader!=null){
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
URLConnection类:
- java.net.URLConnection代表的是一种连接。
- URLConnection用于读取和写入对应URL 引用的资源。
- URLConnection对象操作步骤:
- 通过在 URL 上调用 openConnection 方法创建连接对象;
- 设置参数和一般请求属性。
- 使用 connect 方法建立到远程对象的实际连接;
- 远程对象变为可用,其中远程对象的头字段和内容变为可访问。
- URL的方法openStream():能从网络上读取数据
- 若希望输出数据,例如向服务器端的CGI (公共网关接口-Common Gateway Interface-的简称,是用户浏览器和服务器端的应用程序进行连接的接口)程序发送一些数据,则必须先与URL建立连接,然后才能对其进行读写,此时需要使用URLConnection。
- URLConnection:表示到URL所引用的远程对象的连接。当与一个URL建立连接时,首先要在一个URL 对象上通过方法openConnection() 生成对应的URLConnection对象。如果连接过程失败,将产生IOException.
public Object getContent( ) throws IOException
public intgetContentLength( )
public String getContentType( )
public long getDate( )
public long getLastModified( )
public InputStreamgetInputStream( )throws IOException
public OutputSteramgetOutputStream( )throws IOException
import java.io.*;
import javax.servlet.ServletException;
import javax.servlet.http.*;
public class DataServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("doGet方法");
dealRequest(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("doPost方法");
dealRequest(request, response);
}
private void dealRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException{
String name = request.getParameter("name");
name = new String(name.getBytes("ISO-8859-1"), "UTF-8");
// String message = request.getParameter("message");
// message = new String(message.getBytes("ISO-8859-1"), "UTF-8");
System.out.println(name+":");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
response.setContentType("text/html;charset=utf-8");
PrintWriter printWriter = response.getWriter();
printWriter.print("你好客户端");
printWriter.flush();
printWriter.close();
}
}
public class TestURLConnection_1 {
public static void main(String args[]) {
try {
URL url = new URL("http://127.0.0.1/URLwangluo/DataServlet");
URLConnection urlConnection = url.openConnection();
HttpURLConnection httpURLConnection = (HttpURLConnection) urlConnection;
httpURLConnection.setConnectTimeout(5000);
httpURLConnection.setRequestMethod("POST");
httpURLConnection.setDoOutput(true);
httpURLConnection.setDoInput(true);
httpURLConnection.setUseCaches(false);
httpURLConnection.setRequestProperty("accept", "*/*");
httpURLConnection.setRequestProperty("connection", "Keep-Alive");
httpURLConnection.connect();
OutputStream outputStream = httpURLConnection.getOutputStream();
outputStream.write("name=你好,服务器".getBytes());
outputStream.flush();
outputStream.close();
int responseCode = httpURLConnection.getResponseCode();
if(responseCode==200){
InputStream inputStream = httpURLConnection.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String oneLineData;
while ((oneLineData = bufferedReader.readLine()) != null){
System.out.println(oneLineData);
}
bufferedReader.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
中间也可以这样写
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
public class TextURLconnection_2 {
public static void main(String args[]) {
String sendData = "name=你好,客户端";
try {
// 1、通过在 URL 上调用 openConnection 方法创建连接对象
URL url = new URL("http://127.0.0.1/URLwangluo/DataServlet");
// 根据URL获取URLConnection对象
URLConnection urlConnection = url.openConnection();
// 请求协议是HTTP协议,故可转换为HttpURLConnection对象
HttpURLConnection httpURLConnection = (HttpURLConnection) urlConnection;
// 2、设置参数和一般请求属性
// 设置连接超时时间5秒
httpURLConnection.setConnectTimeout(5000);
// 设定请求的方法为POST,默认是GET
httpURLConnection.setRequestMethod("POST");
// 请求如果是Post,参数要放在请求体里,所以要向httpURLConnection输出参数
httpURLConnection.setDoOutput(true);
// 设置是否从httpUrlConnection读入,默认情况下是true;
httpURLConnection.setDoInput(true);
// 请求如果是Post,不能使用缓存
httpURLConnection.setUseCaches(false);
// 设置通用的请求属性
httpURLConnection.setRequestProperty("accept", "*/*");
httpURLConnection.setRequestProperty("connection", "Keep-Alive");
// 3、使用 connect 方法建立到远程对象的实际连接
httpURLConnection.connect();
// 4、远程对象变为可用
// 通过HttpURLConnection获取输出输入流:
// 向服务器发送数据
OutputStream outputStream = httpURLConnection.getOutputStream();
PrintWriter printWriter = new PrintWriter(outputStream);
// 发送请求参数
printWriter.print(sendData);
// flush输出流的缓冲
printWriter.flush();
printWriter.close();
// 响应码 200表示成功
int responseCode = httpURLConnection.getResponseCode();
if(responseCode==200){
// 获取服务器端的响应数据
InputStream inputStream = httpURLConnection.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String oneLineData;
while ((oneLineData = bufferedReader.readLine()) != null){
System.out.println(oneLineData);
}
bufferedReader.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
URI、URL和URN的区别
URI,是uniform resource identifier,统一资源标识符,用来唯一的标识一个资源。而URL是uniform resource locator,统一资源定位符,它是一种具体的URI,即URL可以用来标识一个资源,而且还指明了如何locate这个资源。而URN,uniform resource name,统一资源命名,是通过名字来标识资源,比如mailto:java-net@java.sun.com。也就是说,URI是以一种抽象的,高层次概念定义统一资源标识,而URL和URN则是具体的资源标识的方式。URL和URN都是一种URI。
在Java的URI中,一个URI实例可以代表绝对的,也可以是相对的,只要它符合URI的语法规则。而URL类则不仅符合语义,还包含了定位该资源的信息,因此它不能是相对的。
位于网络中的计算机具有唯一的IP地址,这样不同的主机可以互相区分。
客户端-服务器是一种最常见的网络应用程序模型。服务器是一个为其客户端提供某种特定服务的硬件或软件。客户机是一个用户应用程序,用于访问某台服务器提供的服务。端口号是对一个服务的访问场所,它用于区分同一物理计算机上的多个服务。套接字用于连接客户端和服务器,客户端和服务器之间的每个通信会话使用一个不同的套接字。TCP协议用于实现面向连接的会话。
Java 中有关网络方面的功能都定义在java.net 程序包中。Java 用InetAddress对象表示IP 地址,该对象里有两个字段:主机名(String) 和IP 地址(int)。
类Socket 和ServerSocket实现了基于TCP协议的客户端-服务器程序。Socket是客户端和服务器之间的一个连接,连接创建的细节被隐藏了。这个连接提供了一个安全的数据传输通道,这是因为TCP 协议可以解决数据在传送过程中的丢失、损坏、重复、乱序以及网络拥挤等问题,它保证数据可靠的传送。
类URL 和URLConnection提供了最高级网络应用。URL 的网络资源的位置来同一表示Internet 上各种网络资源。通过URL对象可以创建当前应用程序和URL 表示的网络资源之间的连接,这样当前程序就可以读取网络资源数据,或者把自己的数据传送到网络上去。
端口:
物理端口:
逻辑端口:用于标识进程的逻辑地址,不同进程的标识;有效端口:0~65535,其中0~1024系统使用或保留端口。
java 中ip对象:InetAddress.
import java.net.*;
class IPDemo{
public static void main(String[] args) throws UnknownHostException{
//通过名称(ip字符串or主机名)来获取一个ip对象。
InetAddress ip = InetAddress.getByName ("www.baidu.com"); //java.net.UnknownHostException
System.out.println("addr:"+ip.getHostAddress());
System.out.println("name:"+ip.getHostName());
}
}
java.net. InetAddress类表示互联网协议 (IP) 地址,
该类有如下常用方法:
static InetAddress getLocalHost():返回本地主机的InetAddress对象。
static InetAddress getByName(String host):通过主机名(可以是域名,也可以是其 IP 地址的文本表示形式)获得InetAddress对象。
String getHostAddress():返回字符串类型的IP地址。
import java.net.InetAddress;
public class GetIP_0 {
public static void main(String args[]) {
try {
//获得本地主机的IP地址
// 通过InetAddress类的静态方法,返回本地主机对象
InetAddress inetAddress = InetAddress.getLocalHost();
// 通过InetAddress类的getHostAddress()获得IP地址字符串
String hostAddress01 = inetAddress.getHostAddress();
System.out.println("本机IP地址为:"+hostAddress01);
//获取域名在互联网上的IP地址
String domainName = "www.baidu.com";
// 通过InetAddress类的静态方法,返回指定域名的IP地址对象
InetAddress inetAddress02 = InetAddress.getByName(domainName);
// 通过InetAddress类的getHostAddress()获得IP地址字符串
String hostAddress02 = inetAddress02.getHostAddress();
System.out.println("百度IP地址为:"+hostAddress02);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Socket:套接字,通信的端点。
就是为网络服务提供的一种机制,通信的两端都有Socket,网络通信其实就是Socket间的通信,数据在两个Socket间通过IO传输。
套接字(Socket)的引入
为了能够方便的开发网络应用程序,由美国伯克利大学在Unix上实现的一种应用程序访问网络的通信协议Socket,Socket的出现使程序员可以很方便的访问TCP/IP.
网络通信的三要素:
- IP地址
- 端口号
- 通讯协议
Socket通常也称作“套接字”,应用程序通常通过“套接字”向网络发出请求或者应答网络请求。
Socket是连接运行在网络上的两个程序间的双向通讯端点
利用套接字(Socket)开发网络应用程序早已被广泛的采用,以至于成为事实上的标准。
网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。
通信的两端都要有Socket,是两台机器间通信的端点。
网络通信其实就是Socket间的通信。
Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO传输。
一般主动发起通信的应用程序属客户端,等待通信请求的为服务端。
Socket分类:
流套接字(stream socket):使用TCP提供可依赖的字节流服务
数据报套接字(datagram socket):使用UDP提供“尽力而为”的数据报服务
Socket类的常用构造器:
- public Socket(InetAddressaddress,intport)创建一个流套接字并将其连接到指定IP地址的指定端口号。
- public Socket(Stringhost,intport)创建一个流套接字并将其连接到指定主机上的指定端口号。
lSocket类的常用方法:
- public InputStream getInputStream()返回此套接字的输入流。可以用于接收网络消息
- public OutputStream getOutputStream()返回此套接字的输出流。可以用于发送网络消息
- public InetAddress getInetAddress()此套接字连接到的远程IP地址;如果套接字是未连接的,则返回null。
- public InetAddress getLocalAddress()获取套接字绑定的本地地址。即本端的IP地址
- public intgetPort()此套接字连接到的远程端口号;如果尚未连接套接字,则返回0。
- public intgetLocalPort()返回此套接字绑定到的本地端口。如果尚未绑定套接字,则返回-1。即本端的端口号。
- public void close()关闭此套接字。套接字被关闭后,便不可在以后的网络连接中使用(即无法重新连接或重新绑定)。需要创建新的套接字对象。关闭此套接字也将会关闭该套接字的InputStream和OutputStream。
- public void shutdownInput()如果在套接字上调用shutdownInput()后从套接字输入流读取内容,则流将返回EOF(文件结束符)。即不能在从此套接字的输入流中接收任何数据。
- public void shutdownOutput()禁用此套接字的输出流。对于TCP套接字,任何以前写入的数据都将被发送,并且后跟TCP的正常连接终止序列。如果在套接字上调用shutdownOutput()后写入套接字输出流,则该流将抛出IOException。即不能通过此套接字的输出流发送任何数据。
UDP传输:
1,只要是网络传输,必须有socket 。
2,数据一定要封装到数据包中,数据包中包括目的地址、端口、数据等信息。
直接操作udp不可能,对于java语言应该将udp封装成对象,易于我们的使用,这个对象就是DatagramSocket. 封装了udp传输协议的socket对象。
因为数据包中包含的信息较多,为了操作这些信息方便,也一样会将其封装成对象。这个数据包对象就是:DatagramPacket.通过这个对象中的方法,就可以获取到数据包中的各种信息。
基于UDP的Socket通信过程;
UDP是用户数据报协议
基于UDP的Socket编程是一种非连接的Socket通信,它提供的是无连接、不可靠信息传送服务。
DatagramSocket表示用来发送和接收数据包的套接字
DatagramPacket表示数据包
DatagramSocket具备发送和接受功能,在进行udp传输时,需要明确一个是发送端,一个是接收端。
udp的发送端:客户端
1,建立udp的socket服务,创建对象时如果没有明确端口,系统会自动分配一个未被使用的端口。
2,明确要发送的具体数据。
3,将数据封装成了数据包。
4,用socket服务的send方法将数据包发送出去。
5,关闭资源。
import java.net.*;
public class UDPClient {
public static void main(String args[]){
DatagramSocket datagramSocket = null;
try {
// 1.创建数据包套接字,端口号9999, 建立udp的socket服务。
datagramSocket = new DatagramSocket(9999);
//2,明确要发送的具体数据。
byte [] sendData = "你好服务器端".getBytes();
// 3.根据主机名和端口号创建套接字地址
InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1", 8888);
// 4.创建发送的数据包
DatagramPacket datagramPacket = new DatagramPacket(sendData, sendData.length, inetSocketAddress);
//5. 发送数据
datagramSocket.send(datagramPacket);//
} catch (Exception e) {
e.printStackTrace();
}finally{
if(datagramSocket!=null){
//6,关闭资源。
datagramSocket.close();// 关闭DatagramSocket
}
}
}
}
udp的接收端:服务端
1,创建udp的socket服务,必须要明确一个端口,作用在于,只有发送到这个端口的数据才是这个接收端可以处理的数据。
2,定义数据包,用于存储接收到数据。
3,通过socket服务的接收方法将收到的数据存储到数据包中。
4,通过数据包的方法获取数据包中的具体数据内容,比如ip、端口、数据等等。
5,关闭资源。
import java.net.*;
public class UDPServer {
public static void main(String args[]){
DatagramSocket datagramSocket = null;
try {
//1.创建数据报包的套接字,端口号8888
datagramSocket = new DatagramSocket(8888);
//2,定义数据包,用于存储接收到数据。先定义字节数组,数据包会把数据存储到字节数组中。
byte[] bufferArray = new byte[1024];
// 创建接收的数据报包
DatagramPacket datagramPacket = new DatagramPacket(bufferArray, bufferArray.length);
//3,通过socket服务的接收方法将收到的数据存储到数据包中。
datagramSocket.receive(datagramPacket);// 接受数据
// 4,通过数据包的方法获取数据包中的具体数据内容,比如ip,端口,数据等等。
// String ip = dp.getAddress().getHostAddress();
byte [] dataArray = datagramPacket.getData();
int validLength = datagramPacket.getLength();
String result = new String(dataArray, 0, validLength);// 得到数据
System.out.println("服务端:"+result);
} catch (Exception e) {
e.printStackTrace();
}finally{
if(datagramSocket != null){
//5,关闭资源。
datagramSocket.close();// 关闭DatagramSocket
}
}
}
}
TCP传输:
两个端点的建立连接后会有一个传输数据的通道,这通道称为流,而且是建立在网络基础上的流,称之为socket流。该流中既有读取,也有写入。
基于TCP的Socket通信过程
使用TCP/IP的套接字(Socket)进行通信,安全性高。
服务器程序将一个套接字绑定到一个特定的端口,并通过此套接字等待和监听客户端到端口的连接请求。
客户端程序根据服务器程序所在的主机名和端口发出连接请求。
使用ServerSocket和Socket实现服务器端和客户端的Socket通信
tcp的两个端点:一个是客户端,一个是服务端。
客户端:对应的对象,Socket
服务端:对应的对象,ServerSocket
TCP客户端:
1,建立tcp的socket服务,最好明确具体的地址和端口。这个对象在创建时,就已经可以对指定ip和端口进行连接(三次握手)。
2,如果连接成功,就意味着通道建立了,socket流就已经产生了。只要获取到socket流中的读取流和写入流即可,只要通过getInputStream方法获得输入流和getOutputStream方法获得输出流,进行数据传输。
3,按照一定的协议对Socket 进行读/写操作:通过输入流读取服务器放入线路的信息(但不能读取自己放入线路的信息),通过输出流将信息写入线程。
4,关闭Socket:断开客户端到服务器的连接,释放线路
客户端建立socketAtClient对象的过程就是向服务器发出套接字连接请求
import java.io.*;
import java.net.*;
public class TcpClient {
public static void main(String[] args) {
try{
//连接到服务器端
Socket socket = new Socket("localhost",8888);
// //获取Socket连接的输出对象
// //第一种
OutputStream outputStream = socket.getOutputStream();
outputStream.write("你好服务器!".getBytes());
outputStream.flush();
outputStream.close();
//第二种
OutputStream outputStream = socket.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
//客户端向服务器端发送请求的内容
dataOutputStream.writeUTF("你好服务器");
dataOutputStream.close();
dataInputStream.close();
//获取Socket连接的输入对象
//第一种
InputStream inputStream = socket.getInputStream();
byte[]array=new byte[1024];
int arr=0;
if((arr=inputStream.read(array))!=-1){
System.out.println(new String(array,0,arr));
}
//第二种
InputStream inputStream = socket.getInputStream();
DataInputStream dataInputStream = new DataInputStream(inputStream);
String content = null;
if((content = dataInputStream.readUTF()) != null){
System.err.println(content);
}
socket.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
TCP服务端:
1,创建服务端socket服务,并监听一个端口。
2,服务端为了给客户端提供服务,获取客户端的内容,可以通过accept方法获取连接过来的客户端对象。
3,可以通过获取到的socket对象中的socket流和具体的客户端进行通讯。
4,如果通讯结束,关闭资源。注意:要先关客户端,再关服务端。
import java.io.*;
import java.net.*;
public class TcpServer {
public static void main(String[] args) {
try {
//创建服务端套接字
ServerSocket serverSocket = new ServerSocket(8888);
//监听客户端请求
Socket socket = serverSocket.accept();
//获取Socket连接的输入对象
//第一种
InputStream inputStream = socket.getInputStream();
byte[]array=new byte[1024];
int arr=0;
if((arr=inputStream.read(array))!=-1){
System.out.println(new String(array,0,arr));
}
//第二种
InputStream inputStream = socket.getInputStream();
DataInputStream dataInputStream = new DataInputStream(inputStream);
String content = null;
//读取来自客户端的数据
if ((content = dataInputStream.readUTF()) != null) {
System.out.println("客户端输入内容:" + content);
System.out.println("客户端IP: "+ socket.getInetAddress().getHostAddress());
System.out.println("客户端端口号: " + socket.getPort());
}
dataInputStream.close();
//向客户端写入的数据
//获取Socket连接的输出对象
//第一种
OutputStream outputStream = socket.getOutputStream();
outputStream.write("你好客户端!".getBytes());
outputStream.flush();
outputStream.close();
//第二种
OutputStream outputStream = socket.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
dataOutputStream.writeUTF("你好客户端!");
dataOutputStream.flush();
dataOutputStream.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}