TCP通信的客户端:向服务器发送连接请求,给服务器发送数据,读取服务器回写的数据
表示客户端的类:
java.net.Socket:此类实现客户端套接字。
构造方法:
Socket(String host, int port)
创建一个流套接字并将并将其连接到指定主机上的指定端口号。
参数:
String host:服务器主机的名称/服务器的IP地址
int port:服务器的端口号
成员方法:
OutputStream getOutputStream()返回此套接字的输出流
InputStream getInputStream()返回此套接字的输入流
void close()关闭此套接字
实现步骤:
注意:
public class TCPClient {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1", 8888);
OutputStream os = socket.getOutputStream();
os.write("你好服务器".getBytes());
InputStream is = socket.getInputStream();
byte[] bytes = new byte[1024];
int len = is.read(bytes);
System.out.println(new String(bytes, 0, len));
socket.close();
}
}
TCP通信的服务器端:接收客户端的请求,读取客户端发送的数据,给客户端回写数据。
表示服务器的类:
java.net.ServerSocket:此类实现服务器套接字
构造方法:
ServerSocket(int port)
创建绑定到特定端口的服务器套接字
成员方法:
Socket accept()侦听并接收到此套接字的连接
服务器的实现步骤
public class TCPServer {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(8888);
Socket socket = server.accept();
InputStream is = socket.getInputStream();
byte[] bytes = new byte[1024];
int len = is.read(bytes);
System.out.println(new String(bytes, 0, len));
OutputStream os = socket.getOutputStream();
os.write("收到,谢谢".getBytes());
socket.close();
server.close();
}
}
配合使用FileInputStream和Socket类实现客户端、服务器端的文件上传。
客户端:
public class Client {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1", 8888);
OutputStream os = socket.getOutputStream();
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\work_space\\demo.mkv"));
int len = 0;
byte[] bytes = new byte[1024];
System.out.println("正在上传......");
while((len = bis.read(bytes)) != -1){
os.write(bytes, 0, len);
}
/*
上传完文件,给服务器写一个结束标记
void shutdownOutput()禁用此套接字的输出流
对于TCP套接字,任何以前写入的数据都将被发送,并且后跟TCP正常连接中止序列。
*/
socket.shutdownOutput();
InputStream is = socket.getInputStream();
while((len = is.read(bytes)) != -1){
System.out.println(new String(bytes, 0, len));
}
bis.close();
socket.close();
}
}
服务器:
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(8888);
Socket socket = server.accept();
InputStream is = socket.getInputStream();
File file = new File("D:\\work_space\\Project01\\src\\demo18net\\fileupload");
if(!file.exists()){
file.mkdir();
}
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file + "\\upload.mkv"));
int len = 0;
byte[] bytes = new byte[1024];
System.out.println("正在接收数据......");
long start = System.currentTimeMillis();
while((len = is.read(bytes)) != -1){
bos.write(bytes, 0, len);
}
long end = System.currentTimeMillis();
System.out.println("上传用时: " + (end - start) + "ms.");
OutputStream os = socket.getOutputStream();
os.write("上传完成".getBytes());
bos.close();
socket.close();
}
}
注意:如果客户端的Socket对象没有调用shutdownOutput()方法,服务器的read方法读取不到文件的结束标记,使得read方法进入阻塞状态,一直等待数据读取,于是服务器的后续语句将得不到执行。
对于上面的示例有以下几个问题:
FileOutputStream fis = new FileOutputStream(System.currentTimeMillis() + ".jpg");
BufferedOutputStream bos = new BufferedOutputStream(fis);
while(true){
Socket socket = server.accept();
//file transfer
}
SocketServer server = new SocketServer(8888);
while(true){
Socket socket = server.accept();
new Thread(new Runnable() {
@Override
public void run(){
//完成文件上传
}
});
}
注意:Runnable接口的run方法没有抛出异常,所以要用try-catch块捕捉IOException。
改进后服务器如下:
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(8888);
while(true){
Socket socket = server.accept();
/*
使用多线程技术,提高程序效率
有一个客户端上传文件,就开启一个线程,完成文件的上传
*/
new Thread(new Runnable() {
//完成文件的上传
@Override
public void run() {
try{
InputStream is = socket.getInputStream();
String path = "D:\\work_space\\Project01\\src\\demo18net\\fileupload\\";
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(path + System.currentTimeMillis() + ".mkv"));
int len = 0;
byte[] bytes = new byte[1024];
System.out.println(Thread.currentThread().getName() + "正在接收数据......");
long start = System.currentTimeMillis();
while((len = is.read(bytes)) != -1){
bos.write(bytes, 0, len);
}
long end = System.currentTimeMillis();
System.out.println("上传用时: " + (end - start) + "ms.");
OutputStream os = socket.getOutputStream();
os.write("上传完成".getBytes());
bos.close();
socket.close();
}
catch(Exception e){
e.printStackTrace();
}
}
}).start();
}
}
}