ネットワークプログラミング(ソケット)
跟网络相关的操作实质都是数据传输。
通过IO流在网络上实现数据传输。
网络模型---物理层---数据链路层---网络层---传输层(TCP/UDP)---会话层---表示层---应用层
IP地址---确定主机在网络世界中的位置。
分类 IPV4 四位0-255来组成
IPV6四位16进制的数
端口---用于和计算机外界进行数据交互的媒介。
端口号---端口的标记 0-65535来表示。
域名---域名可以和IP地址进行一一映射。
IPとポート
package com.hst.netio;
import java.net.InetSocketAddress;
/**
* InetSocketAddress
* 1代表IP
* 1地址和端口号的类
* @author Administrator
*
*/
public class InetSocketAddressDemo {
public static void main(String[] args) {
//创建代表IP和端口号的类的对象
InetSocketAddress is = new InetSocketAddress("www.baidu.com",8090);
System.out.println(is.getAddress().toString());//IP地址
System.out.println(is.getHostName().toString());//主机名
System.out.println(is.getPort());//端口号
}
}
UDPとTCP
UDPとTCPのプロセスは異なります
UDP:プロセスは速達のプロセスと似ていますが、独自の宅配便ポイント(ソケットオブジェクト)とパッケージ(データパケットオブジェクト)が必要です。パッケージにも独自のマーク(パッケージ自体、IPアドレス、およびオブジェクトのポートマーク)があります。パッケージのパッケージ化と送信のプロセスは、宅配便ポイント(ソケットオブジェクト)によって実行されます。
UDP
データレシーバー
package com.hst.netio;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
/**
* 1接收发送端发送的内容
* 1接收端要监听数据包的端口号
* 1创建接收数据的数据包
* 1端口是接收数据的链接
* 1数据传输先发送
* @author Administrator
*
*/
public class UDPjieshouDemo {
public static void main(String[] args) throws IOException {
//创建套接字对象 相当于建立一个快递点 来接收寄送的快递 要接收寄送的快递 就要知道快递的编号 即监听端口号
DatagramSocket ds = new DatagramSocket(9090);
//创建接收数据的数据包
//接收端要有字节来接收数据
DatagramPacket dp = new DatagramPacket(new byte[1024],1024);
ds.receive(dp);//接收数据
ds.close();//关流
//解析数据包
System.out.println(dp.getAddress());
System.out.println(dp.getPort());
System.out.println(new String(dp.getData(),0,dp.getLength()));
}
}
データ送信者
package com.hst.netio;
import java.io.IOException;
/**
* 1基于IO流
* 1传输数据时不会建立链接
* 1不可靠的传输方式 不可靠 不安全
* 1传输速度快
* 1底层根据数据包进行数据的传输 数据包的最大值不能超过 64KB
* 1适合传输的场景 直播 语音 视频等
* 1DatagramSocket DatagramPacket
* 1用于UDP
* 0步骤
* 1创建套接字对象 相当于是成立一个快递寄送点
* 2创建数据包 相当于是打包一个包裹 要求有包裹的内容 包裹的寄送目的地 和寄送点 端口号可以作为包裹的标记 地址名是寄送地点
* 3发送数据包 相当于是从快递点寄送包裹
* 4关流
* @author Administrator
*
*/
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
public class UDPfasongDemo {
public static void main(String[] args) throws SocketException {
//创建套接字对象
DatagramSocket ds = new DatagramSocket();
//创建数据包
//第一个参数要发送的数据
//转换为字节数组 默认为字节流
//可以传输的数据的字节个数
//制定地址和端口号
DatagramPacket dp = new DatagramPacket("hello".getBytes(),"hello".length(),new InetSocketAddress("localhost",9090));
//发送数据包
try {
ds.send(dp);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ds.close();//关流
}
//
}
UDPに基づくシンプルなチャットプログラム
package com.hst.netio;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.util.Scanner;
/**
* 1用来建立一个微型的数据传输的聊天室
* 1需要结合线程来实现
* 1一直发送 一直接收
* 1知道发送者和接收端
* @author Administrator
*
*/
public class MiniChatDemo {
public static void main(String[] args) {
new Thread(new ChatSentDemo(),"发送者").start();
new Thread(new Receiv(),"接收者").start();
}
}
//用来代表线程发送的类
class ChatSentDemo implements Runnable{
//
public synchronized void run() {
//
try {
//创建套接字对象
DatagramSocket ds = new DatagramSocket();
Scanner sc = new Scanner(System.in);
//
while(true) {
//一直发送的状态;
byte[] data = sc.next().getBytes();
//创建数据包
DatagramPacket dp = new DatagramPacket(data,data.length,new InetSocketAddress("127.0.0.1",9091));
ds.send(dp);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//
}
}
//代表线程接收的类
class Receiv implements Runnable {
public synchronized void run() {
//创建套接字对象
try {
DatagramSocket ds = new DatagramSocket(9091);
while(true) {
DatagramPacket dp = new DatagramPacket(new byte[1024],1024);
ds.receive(dp);
System.out.println("收到来自"+dp.getAddress()+"的消息"+new String(dp.getData(),0,dp.getLength()));
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
TCP:プロセスは有線電話をかけるのと似ています。まず、電話回線(ソケットオブジェクト)を確立する必要があります。電話回線リンクには2つの条件が必要です。相手の場所(IP)。唯一の一意の回線(ポート)。接続オブジェクトに付属するIOストリーム)電話をかけるときは、電話が鳴ったことを相手に通知する必要があります。
package com.hst.netio;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import org.omg.CORBA.portable.OutputStream;
public class TCPServerDemo {
public static void main(String[] args) throws IOException{
//创建服务器端对象---监听端口
//创建服务器端对象---监听端口
ServerSocket ss= new ServerSocket(9092);//这是一个寄送站
//接受连接
Socket s=ss.accept(); //阻塞
//while(true);
System. out .println(1);
//接受客户端发送数据
//获取自带的字节输入流
InputStream is=s.getInputStream();
//自建缓冲区
byte[]bs= new byte[10];
//
int len=-1;
while((len=is.read(bs))!=-1){
//阻塞
//输出每次读到的内容
System. out .println( new String(bs,0,len));
}
//通知客户端数据已经接受完毕
s.shutdownInput();
//获取自带的字节输出流给客户端发送数据
java.io.OutputStream os = s.getOutputStream();
os.write( "你也好".getBytes());
//通知客户端数据已经发生完毕
s.shutdownOutput();
//关流
ss.close();
}
}
package com.hst.netio;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import org.omg.CORBA.portable.OutputStream;
/**
* 1基于io
* 1可靠安全
* 1传输速度慢
* 1不根据数据包传输数据 没有大小限制
* 1使用场景 聊天 文件
* @author Administrator
*
*/
public class TCPClientDemo {
public static void main(String[]args) throws IOException{
//创建客户端对象
Socket s = new Socket();//建立一个电话设备
//建立连接---阻塞
s.connect( new InetSocketAddress( "127.0.0.1",9092));//创建一条专属的线路 并链接特定用户的标记
//while(true);
//往服务器端发送数据
//获取自带的字节输出流 默认往服务器端写数据
java.io.OutputStream os = s.getOutputStream();//
//通过自带的输出流写出数据
os.write( "您好".getBytes()); //阻塞
/*for(inti=0;i<=100000;i++){
os.write("a".getBytes());
System.out.println(i);
}*/
//通知服务器端数据已经写完
s.shutdownOutput();//将信件内容发送出去
//接受服务器端发送的数据
InputStream is=s.getInputStream();
byte[] bs= new byte[10];
int len=-1;
while((len=is.read(bs))!=-1){
System. out .println( new String(bs,0,len));
}
//通知服务器端数据已经接受完毕
s.shutdownInput();//告诉服务器 收到回信
//关流
s.close();
}
}