一、简单的demo
(1)客户端
package com.songyan.tcp;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream.GetField;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class Demo_Client {
/**
* 1.客户端
* 创建Socket连接服务端(指定ip地址,端口号)通过ip地址找对应的服务器
* 调用Socket的getInputStream()和getOutputStream()方法获取和服务端相连的IO流
* 输入流可以读取服务端输出流写出的数据
* 输出流可以写出数据到服务端的输入流
* @param args
* @throws IOException
* @throws UnknownHostException
*/
public static void main(String[] args) throws UnknownHostException, IOException {
//创建socket
Socket socket=new Socket("127.0.0.1",12345);
//创建输入流
InputStream in=socket.getInputStream();
//创建输出流
OutputStream out=socket.getOutputStream();
//接受服务器返回的数据
byte[] respo=new byte[1024];
int len =in.read(respo);
System.out.println(new String(respo,0,len));
out.write("学习计算机哪家强".getBytes());
}
}
(2)服务器端
package com.songyan.tcp;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Demo_server {
/*2.服务端
* com/songyan/tcp/Demo_server.java
* 创建ServerSocket(需要指定端口号)
* 调用ServerSocket的accept()方法接收一个客户端请求,得到一个Socket
* 调用Socket的getInputStream()和getOutputStream()方法获取和客户端相连的IO流
* 输入流可以读取客户端输出流写出的数据
* 输出流可以写出数据到客户端的输入流*/
public static void main(String[] args) throws IOException {
//创建socket
ServerSocket serversocket=new ServerSocket(12345);
//接受客户端的请求
Socket socket=serversocket.accept();
//获取输入流
InputStream in=socket.getInputStream();
OutputStream out =socket.getOutputStream();
//服务器向客户端写数据
out.write("百度一下你就知道".getBytes());
//服务器读取客户端发送的请求
byte[] respo=new byte[1024];
int len =in.read(respo);
System.out.println(new String(respo,0,len));
}
}
(3)运行
在bin目录下(按住shift右键----在此处打开命令行窗口)
‘
输入start打开另一个窗口
在其中一个窗口,先运行服务器端的程序
在另一个窗口运行客户端的程序
二、TCP代码优化(输入字符串/一行)
(1)客户端
package com.songyan.tcp;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream.GetField;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class Demo2_Client {
/**
* 1.客户端
* 创建Socket连接服务端(指定ip地址,端口号)通过ip地址找对应的服务器
* 调用Socket的getInputStream()和getOutputStream()方法获取和服务端相连的IO流
* 输入流可以读取服务端输出流写出的数据
* 输出流可以写出数据到服务端的输入流
* @param args
* @throws IOException
* @throws UnknownHostException
*/
public static void main(String[] args) throws UnknownHostException, IOException {
//创建socket
Socket socket=new Socket("127.0.0.1",12345);
BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintStream ps=new PrintStream(socket.getOutputStream());
//接受服务器返回的数据
System.out.println(br.readLine());
ps.println("我想报名");
System.out.println(br.readLine());
}
}
(2)服务器端
package com.songyan.tcp;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Demo2_server {
/*2.服务端
* com/songyan/tcp/Demo_server.java
* 创建ServerSocket(需要指定端口号)
* 调用ServerSocket的accept()方法接收一个客户端请求,得到一个Socket
* 调用Socket的getInputStream()和getOutputStream()方法获取和客户端相连的IO流
* 输入流可以读取客户端输出流写出的数据
* 输出流可以写出数据到客户端的输入流*/
public static void main(String[] args) throws IOException {
//创建socket
ServerSocket serversocket=new ServerSocket(12345);
//接受客户端的请求
Socket socket=serversocket.accept();
//获取输入流
BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintStream ps=new PrintStream(socket.getOutputStream());
//服务器向客户端写数据
ps.println("欢迎访问黑马程序员");
System.out.println(br.readLine());
ps.println("爆满了");
}
}
三、服务端是多线程的
多线程的时候只需要修改服务器端
package com.songyan.tcp; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintStream; import java.net.ServerSocket; import java.net.Socket; public class Demo3_server { /*2.服务端 * com/songyan/tcp/Demo_server.java * 创建ServerSocket(需要指定端口号) * 调用ServerSocket的accept()方法接收一个客户端请求,得到一个Socket * 调用Socket的getInputStream()和getOutputStream()方法获取和客户端相连的IO流 * 输入流可以读取客户端输出流写出的数据 * 输出流可以写出数据到客户端的输入流*/public static void main(String[] args) throws IOException { //创建socket ServerSocket serversocket=new ServerSocket(12345); while(true) { final Socket socket=serversocket.accept(); new Thread(){ public void run(){ try { //接受客户端的请求 //获取输入流 BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintStream ps=new PrintStream(socket.getOutputStream()); //服务器向客户端写数据 ps.println("欢迎访问黑马程序员"); System.out.println(br.readLine()); ps.println("爆满了"); } catch (IOException e) { e.printStackTrace(); } } }.start(); } } }
练习题1, 客户端向服务器写字符串(键盘录入),服务器(多线程)将字符串反转后写回,客户端再次读取到是反转后的字符串
(1)客户端
package com.songyan.tcp; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.Socket; import java.util.Scanner; public class Demo5_Client { public static String reversel(String str){ return new StringBuffer(str).reverse().toString(); } /*客户端向服务器写字符串(键盘录入)*/ public static void main(String[] args) throws IOException { //创建Socket Socket socket=new Socket("127.0.0.1",12346); //获取输入流,输出流 BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintStream ps=new PrintStream(socket.getOutputStream()); //接受服务器的数据 String message=br.readLine(); System.out.println(reversel(message)); //再次向客户端发送数据 Scanner in=new Scanner(System.in); ps.println(in.nextLine()); message=br.readLine(); System.out.println(reversel(message)); ps.println(in.nextLine()); } }
(2)服务器端
package com.songyan.tcp; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.ServerSocket; import java.net.Socket; import java.util.Scanner; public class Demo5_server { /*服务器(多线程)将字符串反转后写回, * 客户端再次读取到是反转后的字符串*/ public static void main(String[] args) throws IOException { //创建服务器端socket ServerSocket serverSocket=new ServerSocket(12346); //获取客户端的输入 final Socket socket=serverSocket.accept(); new Thread(){ public void run() { //获取输入流对象,输出流对象 try { BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintStream ps=new PrintStream(socket.getOutputStream()); //输出数据给客户端 Scanner in=new Scanner(System.in); ps.println(in.nextLine()); System.out.println(br.readLine()); ps.println(in.nextLine()); System.out.println(br.readLine()); } catch (IOException e) { e.printStackTrace(); } } }.start(); } }
练习题2, 客户端向服务器上传文件
(1)客户端
package com.songyan.file; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.Socket; import java.net.UnknownHostException; import java.util.Scanner; import javax.xml.ws.handler.MessageContext.Scope; public class Demo1_Client { public static File getFile() { System.out.println("请输入文件路径"); Scanner sc=new Scanner(System.in); String path=sc.nextLine(); //获取文件路径 File file=new File(path); //文件名封装成文件 while(true) { if(!file.exists()) { System.out.println("文件不存在,请重新输入"); }else if(file.isDirectory()) { System.out.println("您输入的是文件夹名称,请输入文件名称"); }else{ return file; } } } public static void main(String[] args) throws UnknownHostException, IOException { //提示输入上传的文件路径,判断路径是否存在,是否是文件夹 File file=getFile(); //发送文件名到服务端 Socket socket=new Socket("127.0.0.1",12345); BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintStream ps=new PrintStream(socket.getOutputStream()); ps.println(file.getName()); //接受结果 String result=br.readLine(); //如果存在,给予提示,程序直接退出 if("存在".equals(result)) { System.out.println("文件已存在"); socket.close(); return; }else{ //如果不存在,定义FileInputStream读取文件,写出到网络 FileInputStream fileIn=new FileInputStream(file); byte[] arr=new byte[8192]; int len; while((len=fileIn.read(arr)) != -1) { ps.write(arr,0,len); } fileIn.close(); socket.close(); } } }
(2)服务器端
package com.songyan.file; import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.ServerSocket; import java.net.Socket; public class Demo1_Server { public static void main(String[] args) throws IOException { //建立多线程服务器 ServerSocket server=new ServerSocket(12345); //读取文件名 while(true) { final Socket socket= server.accept(); new Thread(){ public void run() { try { InputStream in= socket.getInputStream(); BufferedReader br=new BufferedReader(new InputStreamReader(in)); PrintStream ps=new PrintStream(socket.getOutputStream()); String filename=br.readLine(); //判断文件是否存在,结果返回给客户端 File dir=new File("path"); dir.mkdir(); File file=new File(dir,filename); if(file.exists()) { ps.println("存在"); socket.close(); return; }else{ ps.println("不存在"); } //定义FileOutputStream,从网络读取数据存储到本地 FileOutputStream out=new FileOutputStream(file); byte[] arr= new byte[8192]; int len ; while((len=in.read(arr))==-1) { out.write(arr,0,len); } out.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } }.start(); } } }
运行后在项目的根路径下就会创建path文件夹,文件夹中就会包括上传的文件(这里这个文件夹就是模拟的服务器中的文件夹)