用自己字节流实现一发一收的。
服务器端:?
package socket;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws IOException {
//1.在本机的9999端口监听,等待连接,要求本机没有其他服务在监听9999
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("服务端,在9999端口正在监听");
//2.在没有客户端连接9999端口的时候,程序会阻塞,等待连接
Socket socket = serverSocket.accept();//正在等待连接,若有客户机连接的话,就会返回一个socket对象。
//我们必须拿到这个socket对象。
//通过socket 获得 客服端发送到输出流。
InputStream inputStream = socket.getInputStream();
//读取数据
byte[] buf = new byte[1024];
int readLen = 0;
while((readLen = inputStream.read(buf))!= -1){
System.out.println(new String(buf,0,readLen));//根据读取到的实际长度,显示内容
}
OutputStream outputStream = socket.getOutputStream();
outputStream.write("hello,client".getBytes());
//设置结束标记
socket.shutdownOutput();
while((readLen = inputStream.read(buf))!= -1){
System.out.println(new String(buf,0,readLen));//根据读取到的实际长度,显示内容
}
//关闭流 和 socket
inputStream.close();
socket.close();
outputStream.close();
serverSocket.close();//服务器端的socketServer也需要关闭。
//serverSocket可以对应多个socket,只要有一个accept就能得到一个socket。
//这是因为有可能有多个客户端来连接服务器。就是客户端连接啊。【】
}
}
客户端:
package socket;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
public class SocketTcpClient01 {
public static void main(String[] args) throws IOException {
//1.连接服务器的和端口,因为我是本机监听,所以就是写的得到本机地址。也可以写域名啥的。
//连接本机的9999端口号。连接成功的话就是返回socket对象。
Socket socket = new Socket(InetAddress.getLocalHost(),9999);
System.out.println("网络端的socket=" + socket.getClass());
//得到和socket相关联的输出流对象
OutputStream outputStream = socket.getOutputStream();
//通过输出流,写数据到数据通道(因为我是客户端)
outputStream.write("hello,server".getBytes());//需要的是字符数组
//设置结束标记
socket.shutdownOutput();
//读来自服务器端的数据
InputStream inputStream = socket.getInputStream();
byte[] buf = new byte[1024];
int readLen = 0;
while((readLen = inputStream.read(buf))!= -1){
System.out.println(new String(buf,0,readLen));
}
//
//4.关闭流 和 socket ,必须关闭!!!
outputStream.close();
socket.close();
System.out.println("客户端关闭");
//IO流一定要先关闭,socket要最后关闭
//设置写入结束标记。
}
}
使用字符流实现一发一收。
客户端:
package socket;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
public class SocketTcpClient01 {
public static void main(String[] args) throws IOException {
//1.连接服务器的和端口,因为我是本机监听,所以就是写的得到本机地址。也可以写域名啥的。
//连接本机的9999端口号。连接成功的话就是返回socket对象。
Socket socket = new Socket(InetAddress.getLocalHost(),9999);
System.out.println("网络端的socket=" + socket.getClass());
//得到和socket相关联的输出流对象
OutputStream outputStream = socket.getOutputStream();
//我们希望使用字符流(其实是底层的字节流转换成的字符流),同时使用包装流来实现数据传输。
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
//使用转换流实现字节流到字符流的转换,在使用包装流。
bufferedWriter.write("hello,server zifuliu ");
bufferedWriter.newLine();//插入一个换行符,表示写入的内容结束,注意,要求数据的另外一方使用readLine();@!!!
bufferedWriter.flush();//如果使用字符流,需要手动刷新,否则数据不会写入数据通道。
//读来自服务器端的数据
InputStream inputStream = socket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String s = bufferedReader.readLine();
System.out.println(s);
//
//4.关闭流 和 socket ,必须关闭!!!
bufferedReader.close();
bufferedWriter.close();//关闭的顺序就知道先read再writer
socket.close();
System.out.println("客户端关闭");
//IO流一定要先关闭,socket要最后关闭
//设置写入结束标记。
}
}
服务器端:
package socket;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws IOException {
//1.在本机的9999端口监听,等待连接,要求本机没有其他服务在监听9999
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("服务端,在9999端口正在监听");
//2.在没有客户端连接9999端口的时候,程序会阻塞,等待连接
Socket socket = serverSocket.accept();//正在等待连接,若有客户机连接的话,就会返回一个socket对象。
//我们必须拿到这个socket对象。
//通过socket 获得 客服端发送到输出流。
InputStream inputStream = socket.getInputStream();
//读取数据字符流,使用了转换流
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String s = bufferedReader.readLine();
System.out.println(s);
OutputStream outputStream = socket.getOutputStream();
//使用字符输出流的方式回复信息
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
bufferedWriter.write("hello, client,字符流");
bufferedWriter.newLine();//插入一个换行符,表示内容的结束
bufferedWriter.flush();//要手动刷新
outputStream.write("hello,client".getBytes());
//设置结束标记
socket.shutdownOutput();
//关闭流 和 socket
bufferedReader.close();
bufferedWriter.close();
socket.close();
serverSocket.close();//服务器端的socketServer也需要关闭。
//serverSocket可以对应多个socket,只要有一个accept就能得到一个socket。
//这是因为有可能有多个客户端来连接服务器。就是客户端连接啊。【】
}
}
实现图片的发送:
服务器端:
package linear;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class UploadServer {
public static void main(String[] args) throws Exception {
//1.服务器端在监听8888端口
ServerSocket serverSocket = new ServerSocket(8888);
System.out.println("服务器端正在监听8888端口");
//2.等待连接
Socket socket = serverSocket.accept();
//连接成功之后先获取一个输入流
InputStream inputStream = socket.getInputStream();
//转成Buffer类型的
BufferedInputStream bis = new BufferedInputStream(inputStream);
byte[] bytes = StreamUtils.streamToByteArray(bis);//通过工具类,将传过来的数据读入到数组中去,已经拿到数组中去了
//4.将得到的数组,写入到指定的路径,就得到一个文件了。
String destFilePath = "src\\woaini.png";
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFilePath));
bos.write(bytes);
bos.close();
//返回给客户端:我已经收到了
OutputStream outputStream = socket.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));
writer.write("收到图片");
writer.newLine();
writer.flush();//把内容刷新到数据通道
writer.close();
//关闭其他资源
bis.close();
socket.close();
serverSocket.close();
}
}
客户端:
package linear;
import socket.IO;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
public class UploadClient {
public static void main(String[] args) throws Exception {
//1.创建客户端连接到8888端口
Socket socket = new Socket(InetAddress.getLocalHost(),8888);
//2.创建读取磁盘文件的输入流
String filePath = "e:\\hi.PNG";
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath));
byte[] bytes = StreamUtils.streamToByteArray(bis);//byte里就是filePath里面的数据啦
//通过socket获取输出流,将bytes数据发送给服务器
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
bos.write(bytes);//将文件对应的字节数组写入到数据通道中去。
socket.shutdownOutput();//设置写入数据的结束标记。必须要设置的。
InputStream inputStream = socket.getInputStream();
//使用StreamUtils 方法 将数据通道中的数据 转成字符串
String s = StreamUtils.streamToString(inputStream);
System.out.println(s);
inputStream.close();
bos.close();
bis.close();
socket.close();
}
}
一个StreamUtils类:
package linear;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* 此类用于演示关于流的读写方法
*
*/
public class StreamUtils {
/**
* 功能:将输入流转换成byte[], 即可以把文件的内容读入到byte[]
* @param is
* @return
* @throws Exception
*/
public static byte[] streamToByteArray(InputStream is) throws Exception{
ByteArrayOutputStream bos = new ByteArrayOutputStream();//创建输出流对象
byte[] b = new byte[1024];//字节数组
int len;
while((len=is.read(b))!=-1){//循环读取
bos.write(b, 0, len);//把读取到的数据,写入bos
}
byte[] array = bos.toByteArray();//然后将bos 转成字节数组
bos.close();
return array;
}
/**
* 功能:将InputStream转换成String
* @param is
* @return
* @throws Exception
*/
public static String streamToString(InputStream is) throws Exception{
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder builder= new StringBuilder();
String line;
while((line=reader.readLine())!=null){
builder.append(line+"\r\n");
}
return builder.toString();
}
}
|