一、目的
学习Socket(套接字)网络编程。
二、知识点
1.基本知识
2.IP地址和端口号
3.Socket
4.实现服务器端和客户端传输数据:注意端口号必须相同 先运行Server 再运行Client
//模拟客户端
class MyClient{
//要运行起来
public static void main(String[] args) {
//创建用于通信的socket 即指明和谁通信:IP地址 端口号
Socket socket = null;
try {
socket = new Socket("10.129.2.205",8989);
//接收服务器端的信息
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = null;
while((line = br.readLine()) !=null){
System.out.println(line);
}
} catch (IOException e) {
System.out.println("网络出错 请重新登录");
}finally{
//关闭链接
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//模拟服务器端
class MyServer{
public static void main(String[] args){
//1.创建服务器端的serversocket
try(ServerSocket ss = new ServerSocket(8989)) {//错了直接关闭括号里的,就不用finally
//监听客户端
Socket socket = ss.accept();
//从终端接收数据
BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
//向客户端输出数据输出流
PrintStream ps = new PrintStream(socket.getOutputStream());
String line = null;
while((line = keyin.readLine())!= null){
//发送给客户端
// System.out.println(line);
ps.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
5.客户端向服务器端发送图片
准备一张图片的保存路径作为原路径,以及当前代码的保存路径作为传输后的保存路径(这个可自己挑选,只需要运行完毕后查看该路径下是否出现传输的图片)
class Client{
public static void main(String[] args) throws IOException {
//链接服务器端 获取socket
Socket socket = new Socket("10.129.2.205",8000);
//创建服务器端的输入流 用于接收服务器端发来的数据
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println(br.readLine());
//向服务器端发送图片
//第一步 将文件写入内存
String path = "F:/烟炊集/jjl.jpg";
FileInputStream fis = new FileInputStream(path);
//第二步 将文件输出到服务器端
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
//第三步 将文件的内容一点点的传输给服务器
byte[] buf = new byte[1024];//用的是字节流 //可以用字符流
int len = -1;
while((len = fis.read(buf))!=-1 ) {
bos.write(buf,0,len);
}
socket.shutdownOutput();
}
}
class Server{
public static void main(String[] args) throws IOException {
//创建服务器端的serversocket
ServerSocket ss = new ServerSocket(8000);
//监听客户端链接
//当有客户端来连接这个服务器 就可以得到对应的socket
//当没有客户端来链接 服务器一直在这里等待
Socket socket = ss.accept();
//创建客户端对应的输出流 用于向这个客户端发送数据
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("链接成功,可以发送数据");
//接收客户端传输来的文件
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
//文件对应的输出流
String path = "F:/Androidstudio/java2/src/main/java/day12/media/LL.jpg";
FileOutputStream fos = new FileOutputStream(path);
byte[] buf = new byte[1024];//用的是字节流 //可以用字符流
int len = -1;
while((len = bis.read(buf))!=-1 ) {
fos.write(buf,0,len);
}
socket.shutdownOutput();
}
}
运行效果:
三、实际应用
1.对聊:实现效果如下
/**
* 服务器端和客户端都可以随意的发送对话内容
* 从终端输入
*
* 客户端:
* 主线程:接收终端输入 将终端的输入发送给服务器端
* 子线程:接收服务器端发来的数据
* 服务器端:
* 主线程:接收终端输入 将终端的输入发送给客户端
* * 子线程:接收客户端发来的数据
*/
代码
客户端:
class Client{
public static void main(String[] args) throws IOException {
Socket socket = new Socket("10.129.2.205",8000);
//子线程 处理服务端数据
new Thread(new ClientThread(socket)).start();
BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
//客户端的输出流对象
PrintStream printStream = new PrintStream(socket.getOutputStream());
String line = null;
while ((line = keyin.readLine())!= null){
printStream.println(line);
}
}
}
服务器端
class Server{
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8000);
Socket socket = serverSocket.accept();
new ServerThread(socket).start();
//终端输入流对象
BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
//客户端的输出流对象
PrintStream printStream = new PrintStream(socket.getOutputStream());
//读取终端的输入 输出给客户端
String line = null;
while ((line = keyin.readLine())!= null){
printStream.println(line);
}
}
}
创建一个子线程 给服务器端用于处理、接收客户端的数据
class ServerThread extends Thread{
private Socket socket;
public ServerThread(Socket socket){
this.socket = socket;
}
@Override
public void run() {
BufferedReader bufferedReader = null;
try {
bufferedReader= new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = null;
while ((line = bufferedReader.readLine())!=null){
System.out.println(line);
}
} catch (IOException e) {
System.out.println("网络异常 请重新登录");
}finally {
try{
if(bufferedReader != null){
bufferedReader.close();
}
if (socket!= null){
socket.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
}
}
创建一个子线程 给客户端用于处理、接收服务器端的数据
class ClientThread implements Runnable{
private Socket socket;
//保存操作的socket 对象
public ClientThread(Socket socket){
this.socket = socket;
}
@Override
public void run() {
BufferedReader bufferedReader = null;
try {
//获取输入
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//读取
String line = null;
while ((line=bufferedReader.readLine()) != null){
System.out.println(line);
}
} catch (IOException e) {
System.out.println("网络出错 请重新登录");
System.exit(-1);
}finally {
try {
if (bufferedReader != null) {
bufferedReader.close();
}
if (socket != null) {
socket.close();
}
}catch (IOException e) {
e.printStackTrace();
}
}
}
}
2.群聊
和对聊只是Server类的区别 需要一个数组来保存所有客户端 发消息的时候是群发用遍历来实现
class Server{
public static ArrayList<Socket> sockets = new ArrayList<>();
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8000);
while (true){
Socket socket = serverSocket.accept();
//当客户连接过来就保存
sockets.add(socket);
new ServerThread(socket).start();
}
}
}
class Client{
public static void main(String[] args) throws IOException {
Socket socket = new Socket("10.129.2.205",8000);
//子线程 处理服务端数据
new Thread(new ClientThread(socket)).start();
BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
//客户端的输出流对象
PrintStream printStream = new PrintStream(socket.getOutputStream());
String line = null;
while ((line = keyin.readLine())!= null){
printStream.println(line);
}
}
}
class ClientThread implements Runnable{
private Socket socket;
//保存操作的socket 对象
public ClientThread(Socket socket){
this.socket = socket;
}
@Override
public void run() {
BufferedReader bufferedReader = null;
try {
//获取输入
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//读取
String line = null;
while ((line=bufferedReader.readLine()) != null){
System.out.println(line);
}
} catch (IOException e) {
System.out.println("网络出错 请重新登录");
System.exit(-1);
}finally {
try {
if (bufferedReader != null) {
bufferedReader.close();
}
if (socket != null) {
socket.close();
}
}catch (IOException e) {
e.printStackTrace();
}
}
}
}
class ServerThread extends Thread{
private Socket socket;
public ServerThread(Socket socket){
this.socket = socket;
}
@Override
public void run() {
BufferedReader bufferedReader = null;
try {
bufferedReader= new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = null;
while ((line = bufferedReader.readLine())!=null){
System.out.println(line);
}
} catch (IOException e) {
System.out.println("网络异常 请重新登录");
}finally {
try{
if(bufferedReader != null){
bufferedReader.close();
}
if (socket!= null){
socket.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
}
}
四、心得
前面学的I/O流的内容感觉又忘了,今天学这个网络的时候也一起复习了。学的东西变多的时候,就要考虑怎么样才能记住前面的了。焦虑是没有用的,现在的焦虑多半是自己付出了,但看不到收获,产生的自我怀疑现象。当你正在为做不成某件事而抱怨苦恼的时候,静下心来想一想,你真正投入的时间和精力有多少,也许你就会知道现在为什么自己是现在这样了。