tcp编程:tcp传输控制协议,能够保证在数据传递不丢失
udp编程:不保证数据能够传递到对象,数据可能丢失
一些名词解释
- socket套接字
- ip地址 :用于确定网络上的计算机
ipv4 4段地址
ipv6 6段地址 - 端口号:
每台计算机都有65536个端口 0-65535
能够访问计算机的”门”
特殊的内置端口:- 80端口:http协议的默认端口 超文本传输协议
- 21端口:ftp协议的默认端口 文件传输协议
- 25端口:smtp协议的默认端口 邮件传输协议
- tcp/ip:传输控制协议/网络协议
socket套接字
用于描述ip地址和端口号,是一个通讯链的句柄(java的引用)
在internet上的一个主机,一般运行多少个服务软件,同时就提供多少个服务,每个服务监听一个端口,不同的端口,对应不同的服务,最终应用程序和服务器通过socket套接字建立网络连接,发送请求和接受请求
服务端套接字
ServerSocket类
- Socket accetp();
用于监听并接受到套接字的连接 - void close();
关闭socket - InetAddress getInetAddress()
返回自服务器套接字的本地地址 - int getLocalport()
返回此套接字在其上的监听的端口号客户端套接字
Socket类
- Socket(String host,int port);
创建一个套接字并将其连接到指定的ip地址,和这个ip地址对应的端口号 - void socket()
关闭socket - InetAddress getInetAddress()
返回自服务器套接字的本地地址 - int getLocalport()
返回此套接字在其上的监听的端口号
例子一
下载器例子
Client.java(客户端)
/**
* 客户端:
* 1.连接服务端
* 2.从键盘输入服务器计算机中的文件路径,并请求下载
* 3.如果服务端有文件,就返回给客户端文件的名称和文件长度
* 4.从网络上获取服务器下载的文件数据,进入客户端的内存
* 5.把内存的数据写到客户端的硬盘上
*/
public class Client {
public static void main(String[] args)throws IOException {
Scanner input = new Scanner(System.in);
//创建socket对象(ip地址,端口号),连接服务器
Socket socket = new Socket("10.8.38.123",9991);
//构架网络输入输出流
//网络输入流
DataInputStream dis = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
//网络输出流
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
//从客户端获取网络上传递过来的字符串
System.out.println("请输入服务端中的文件的路径");
String filePath = input.next();
//把文件路径发送到网络流
dos.writeUTF(filePath);
dos.flush();
//接收文件的名字
String fileName = dis.readUTF();
//接收文件的长度
String length = dis.readUTF();
//输出
System.out.println("文件在服务端存在,文件名为:"+fileName+" 文件长度:"+length);
//从网络流上接收文件数据,并存储到内存,把内存数据输出到本地硬盘
System.out.println("开始接收文件...");
//构建本地流输出
DataOutputStream dos_local = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("D:/aa/"+fileName)));
//构建缓冲
byte[] buffer = new byte[1024*4];//服务端和客户端缓冲大小一样
//循环从网络流中读入数据进内存
while(true){
int len = -1;
if(dis!=null){
//从网络上读数据
len = dis.read(buffer);
dos_local.write(buffer,0,len);
}
if(len==-1){
break;
}
}
dos_local.close();
dis.close();
dos.close();
socket.close();
System.out.println("接收文件完毕,文件路径d:/aa" +fileName+" 文件大小"+length);
}
}
Server.java(服务器)
/**
* 服务端:给客户端提供服务
* 1.接收客户端发送过来的文件路径,并判断文件是否存在
* 2.获取文件的名称和文件的长度,并写到网络上
* 3.从本服务器硬盘读取文件内容到内存
* 4.把内存的文件数据写到网络上
*
* 一次只能给一个客户端提供服务
*/
public class Server {
public static void main(String[] args) throws Exception {
//创建了一个ServerSocket对象
ServerSocket ss = new ServerSocket(9991);
System.out.println("服务器已经启动");
while (true) {
Socket socket = ss.accept();
//仅代表run逻辑
ThreadHandler th = new ThreadHandler(socket);
Thread t = new Thread(th);
t.start();
}
}
}
ThreadHandler.java(线程控制器)
/**
* 这个run任务逻辑,要给很多个socket提供服务
*/
public class ThreadHandler implements Runnable {
private Socket socket;
public ThreadHandler(Socket socket){
this.socket = socket;
}
@Override
public void run() {
//获取客户端的ip地址
InetAddress ip = socket.getInetAddress();
try {
//构架网络输入输出流
//网络输出流
Scanner input = new Scanner(System.in);
OutputStream os = socket.getOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(os);
DataOutputStream dos = new DataOutputStream(bos);
//网络输入流
DataInputStream dis = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
String filePath = dis.readUTF();
File file = new File(filePath);
if (!file.exists()){
dos.writeUTF("您请求的文件不存在,请换其他文件");
dos.flush(); //清除缓冲,标记数据写出完毕,此时才将数据发送到网络上
return;
}
//能到此处说明文件存在
//获取文件的名称
String fileName = file.getName();
dos.writeUTF(fileName);
dos.flush();
//获取文件的长度
long length = file.length();
dos.writeUTF(length+"");
dos.flush();
//准备开始发送文件
System.out.println(ip.getHostAddress()+" fileName="+fileName+" length="+length);
System.out.println(ip.getHostAddress()+" 开始发送文件...");
//从本地读取文件到内存中(本地流)
DataInputStream dis_local = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
byte[] buffer = new byte[1024*4];
while(true){
int len = -1;
if(dis_local!=null){
//本地流输入
}
if (len==-1){
break;
}
len = dis_local.read(buffer);
dos.write(buffer,0,len);
}
dos.flush();
dos.close();
bos.close();
os.close();
dis.close();
socket.close();//关闭套接字
System.out.println(ip.getHostAddress()+" 文件:"+fileName+"发送完毕");
} catch (Exception e) {
e.printStackTrace();
}
}
}
例子二
对话例子
Client.java(客户端)
/**
* 客户端:
* 1.连接服务端
* 2.从键盘录入字符串,并发送给服务端
* 3.接收服务端发送给客户端的数据并显示
*/
public class Client {
public static void main(String[] args)throws IOException {
Scanner input = new Scanner(System.in);
//创建socket对象(ip地址,端口号),连接服务器
Socket socket = new Socket("10.8.38.123",9991);
//构架网络输入输出流
//网络输入流
DataInputStream dis = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
//网络输出流
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
//从客户端获取网络上传递过来的字符串
System.out.println("请输入给服务端发送的数据");
String sendMessage = input.next();
dos.writeUTF(sendMessage);
dos.flush();//清空缓冲区,写出数据到网络上
String message = dis.readUTF();
System.out.println("服务端回馈的数据:"+message);
dis.close();
dos.close();
socket.close();
}
}
Server.java(服务端)
/**
* 服务端:给客户端提供服务
* 1.接收客户端发送的字符串并显示
* 2.从键盘录入一个字符串,并返回给客户端
*
* 一次只能给一个客户端提供服务
*/
public class Server {
public static void main(String[] args) throws Exception {
//创建了一个ServerSocket对象
ServerSocket ss = new ServerSocket(9991);
System.out.println("服务器已经启动");
while (true) {
Socket socket = ss.accept();
//仅代表run逻辑
ThreadHandler th = new ThreadHandler(socket);
Thread t = new Thread(th);
t.start();
}
}
}
ThreadHandler.java(线程控制器)
/**
* 这个run任务逻辑,要给很多个socket提供服务
*/
public class ThreadHandler implements Runnable {
private Socket socket;
public ThreadHandler(Socket socket){
this.socket = socket;
}
@Override
public void run() {
try {
//构架网络输入输出流
//网络输出流
Scanner input = new Scanner(System.in);
OutputStream os = socket.getOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(os);
DataOutputStream dos = new DataOutputStream(bos);
//网络输入流
DataInputStream dis = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
//从客户端获取网络上传递过来的字符串
String message = dis.readUTF();
System.out.println("客户端的信息:"+message);
System.out.println("请输入给客户端的信息");
String sendMessage = input.next();
dos.writeUTF(sendMessage);//消息没有发送到网络上,写到本地计算机的缓冲中
dos.flush();//清除缓冲,标记数据写出完毕,此时才将数据发送到网络上
dos.close();
bos.close();
os.close();
dis.close();
socket.close();//关闭套接字
} catch (Exception e) {
e.printStackTrace();
}
}
}