网络编程-Socket通信实现服务器与客户端互传文件(JAVA语言实现)
在网络通信协议下,实现网络互连的不同计算机上运行的程序间可以进行数据交换.
网络编程三要素:ip地址、端口、协议
ip地址:
每台计算机指定的一个标识符,127.0.0.1是回送地址,可以代表本机地址 ,一般用来测试使用
ipconfig:命令行中查看本机地址
ping ip地址:检查网络是否连通
端口
两个应用程序的通信。IP地址是可以唯一标识网络中的设备,端口就是可以唯一标识设备中的应用程序。
端口号:用两个字节表示的整数,它的取值范围是0-65535.其中0-1023之间的端口号用于一些知名的网络服务和应用,普遍的应用程序要使用1024以上。
协议:
连接和通信的规则称为网络的通信协议.
常见的协议UDP和tcp
UDP:用户数据报协议.
无连接的通信协议,即使在传输数据的时候,发送端和接收端不建立连接.
消耗资源小,通信效率高.
UDP适用于音频,视频和普通数据的传输.
TCP:传输控制协议
是面向连接的同学,即传输数据之前,在发送端和接收端建立逻辑连接,然后再传输数据.
两台计算机无差错的数据传授.
需要经过三次握手,四次挥手
三次握手:
-
客户端向服务器端发出连接请求,等待服务确认
-
服务器端向客户端回送一个响应,通知客户端收到了连接请求
-
客户端再次向服务器端发送确认信息,确认连接
TCP是可以保证数据的安全的传输,上传文件,下载文件等等
Socket实现客户端向服务器发送文件
先运行服务器,再运行客户端部分的代码。
serverDemo02.java
package demo02;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo02 {
public static void main(String[] args) throws Exception{
//创建服务
ServerSocket serverSocket = new ServerSocket(9000);
//监听客户端连接
Socket socket = serverSocket.accept();//阻塞式监听会一直等待客户端连接
//获取输入流
InputStream is = socket.getInputStream();
//文件输出
File file=new File("E:/receive3.jpg");//接收文件地址
FileOutputStream fos = new FileOutputStream(file);
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
fos.write(buffer,0,len);
}//关闭资源
fos.close();
is.close();
socket.close();
serverSocket.close();
}
}
clientDemo02.java
package demo02;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
public class clientDemo02 {
public static void main(String[] args) throws Exception{
Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9000);
OutputStream os=socket.getOutputStream();
//读取文件流
File file=new File("E:/enginePractise/netStydy/test.jpg");//传输文件地址
//也可以传输txt文件或其他文件,但是客户端服务器端都要更改相应文件后缀名
FileInputStream fis = new FileInputStream(file);
//写出文件
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) != -1) {
os.write(buffer,0,len);
}
//关闭资源
fis.close();
os.close();
socket.close();
}
}
Socket实现服务器端向客户端发送文件
先运行服务器端,再运行客户端代码。
serverDemo03.java
package demo03;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo03 {
public static void main(String[] args) throws Exception{
//创建服务
ServerSocket serverSocket = new ServerSocket(9000);
//监听客户端连接
Socket socket = serverSocket.accept();//阻塞式监听会一直等待客户端连接
OutputStream os=socket.getOutputStream();
//Socket socket=serverSocket.accept();
//读取文件流
File file=new File("upload.txt");
FileInputStream fis = new FileInputStream(file);
//写出文件
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) != -1) {
os.write(buffer,0,len);
//System.out.println(len);
}
//关闭资源
fis.close();
os.close();
socket.close();
serverSocket.close();
}
}
clientDemo03.java
package demo03;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
public class clientDemo03 {
public static void main(String[] args) throws Exception{
Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9000);
//获取输入流
InputStream is = socket.getInputStream();
//文件输出
File file=new File("receiveTest.txt");
FileOutputStream fos = new FileOutputStream(file);
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
//System.out.println(len+"client");
fos.write(buffer,0,len);
}//关闭资源
fos.close();
is.close();
socket.close();
}
}
Socket实现客户端向服务器多次发送文件
通过上面两个例子,我们实现了服务器与客户端之间的发送文件,但是我们会发现一个问题,每次运行完客户端后,客户端和服务器端就终止了,下一次传送文件,又要重新运行服务器端,再运行客户端,但有一种方法,就是只运行一次服务器端,可以一直重复运行客户端。达到一直发送文件的效果。
先运行服务器端,再重复运行客户端。
ServerDemo04.java
package demo04;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ServerDemo04 {
public static void main(String[] args) throws Exception{
//创建服务
ServerSocket serverSocket = new ServerSocket(9000);
ThreadPoolExecutor pool=new ThreadPoolExecutor(10, 10, 60, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(5), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
while(true){
Socket accept = serverSocket.accept();
ThreadSocket ts=new ThreadSocket(accept);
// new Thread(ts).start();
pool.submit(ts);
}
//监听客户端连接
//Socket socket = serverSocket.accept();//阻塞式监听会一直等待客户端连接
}
}
ThreadSocket.java
package demo04;
import java.io.*;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ThreadSocket implements Runnable{
private Socket accept;
public ThreadSocket(Socket accept){
this.accept=accept;
}
@Override
public void run() {
//获取输入流
InputStream is = null;
try {
is = accept.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
//文件输出
File file=new File(new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()).toString()+".jpg");//使得每次运行产生的文件名都不相同
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
byte[] buffer = new byte[1024];
int len;
while (true) {
try {
if (!((len = is.read(buffer)) != -1)) break;
fos.write(buffer,0,len);
} catch (IOException e) {
e.printStackTrace();
}
}//关闭资源
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
accept.close();
} catch (IOException e) {
e.printStackTrace();
}
//socket.close();
//serverSocket.close();
}
}
clientDemo04
package demo04;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
public class clientDemo04 {
public static void main(String[] args) throws Exception{
Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9000);
OutputStream os=socket.getOutputStream();
//读取文件流
File file=new File("E:/enginePractise/netStydy/test.jpg");
FileInputStream fis = new FileInputStream(file);
//写出文件
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) != -1) {
os.write(buffer,0,len);
}
//关闭资源
fis.close();
os.close();
socket.close();
}
}
Socket实现客户端和服务器端互传文件
其实这个也不难,上面几个例子看懂了之后,直接在服务器端和客户端都写上读取写入的方法(就是把上面前两个例子都写上就行了),再另写一个调用例子来运行就好了。
总结
本博客仅作为技术交流和本人学习记录使用,有问题欢迎大家指正。多多交流技术才能更高的理解掌握。