1 演示TCP的传输的客户端和服务端的互访
2 读取客户端键盘输入流,并在服务端将其转换为大写字符将其返回给客户端。
3 通过TCP通讯实现文件上传
4 TCP并发上传图片
TCP通讯过程较为简单,要经过三次握手,在这期间可以反复的接受和发送数据。
1 演示TCP的传输的客户端和服务端的互访
代码如下:
客户端:
public static void main(String[] args) {
try {
Socket s = new Socket("192.168.0.109",10001);//1 建立socket服务。指定要连接的主机端口
OutputStream out = s.getOutputStream();//2 获取socket流中的输出流。将数据写到该流中。通过网络发给服务端
out.write("hello server".getBytes());
InputStream in = s.getInputStream();//3 获取socket中的输入流,将服务端反馈的数据获取到,并打印
byte[] buf = new byte[1024];
int len = in.read(buf);//阻塞式方法,接受服务端返回数据
System.out.println(new String(buf,0,len));
s.close();//4 关闭客户端资源
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
服务端:
public static void main(String[] args) {
try {
ServerSocket ss = new ServerSocket(10001);
Socket s = ss.accept();//阻塞式方法,接受客户端输入数据
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip+"......conntected");
InputStream in = s.getInputStream();//读取客户端发送数据
byte[] buf = new byte[1024];
int len = in.read(buf);
System.out.println(new String(buf,0,len));
OutputStream out = s.getOutputStream();//接收完毕之后,从服务端返回输出语句
out.write("hello you too client".getBytes());
s.close();
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
2 读取客户端键盘输入流,并在服务端将其转换为大写字符将其返回给客户端。
使用缓冲区Buffered
代码如下:
客户端:
public static void main(String[] args){
try {
Socket s = new Socket("192.168.0.109",10001);
BufferedReader br =
new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bfwOUT =
new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));//字节流转字符流
BufferedReader brwIN =
new BufferedReader(new InputStreamReader(s.getInputStream()));
String line = null;
while((line = br.readLine())!=null){
if("over".equals(line)){
break;
}
bfwOUT.write(line);
bfwOUT.newLine();
bfwOUT.flush();
//返回服务端返回的大写数据
String str = brwIN.readLine();
System.out.println(str);
}
br.close();
s.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
服务端:
public static void main(String[] args){
try {
ServerSocket ss = new ServerSocket(10001);
Socket s = ss.accept();//阻塞式方法,接受客户端输入数据
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip+"......conntected");
BufferedReader brwIN =
new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedWriter bfwOUT =
new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));//字节流转字符流
String line = null;
//从客户端读取,在将其转换为大写字符
while((line = brwIN.readLine())!=null){
bfwOUT.write(line.toUpperCase());
bfwOUT.newLine();
bfwOUT.flush();
System.out.println(line);
}
s.close();
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
3 通过TCP通讯实现文件上传
改变的地方仅仅是读取和输出的方式,由字符流变为了文件流。
代码如下:
客户端:
public static void main(String[] args){
try {
Socket s = new Socket("192.168.0.109",10001);
BufferedReader bufr = new BufferedReader(new FileReader("E:/test/output_res.txt"));//改变的地方
PrintWriter out = new PrintWriter(s.getOutputStream(),true);//这种输方式会自动刷新,较二中的BufferedWriter更为方便
String line = null;
while((line = bufr.readLine())!=null){
out.println(line);
}
s.shutdownOutput();//结束标记,告诉服务端,服务已结束,可停止
BufferedReader bufrINT = new BufferedReader(new InputStreamReader(s.getInputStream()));
String str = bufrINT.readLine();
System.out.println(str);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
服务端:
public static void main(String[] args){
try {
ServerSocket ss = new ServerSocket(10001);
Socket s = ss.accept();//阻塞式方法,接受客户端输入数据
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip+"......conntected");
BufferedReader buFIN = new BufferedReader(new InputStreamReader(s.getInputStream()));
PrintWriter out = new PrintWriter(new FileWriter("E:/test/111.txt"),true);
String line = null;
while((line = buFIN.readLine())!=null){
out.println(line);
}
PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
pw.println("上传成功");
} catch (IOException e) {
e.printStackTrace();
}
}
4 TCP并发上传图片
需求:实现服务器多线程上传图片。
4.1 实现单线程上传图片
思路:
1、实现单个线程的图片上传。
2、优化单线程程序。根据多线程的特点,需要将单个线程上传代码中共性的部分提取出来,多线程执行。
那么首先实现单线程图片上传程序:
客户端:
public static void main(String args[]){
try {
//建立连接
Socket s = new Socket("192.168.0.109",10002);
FileInputStream fis = new FileInputStream("E:\\test\\sa.jpg");
OutputStream out = s.getOutputStream();
byte []buf = new byte[1024];
int len = 0;
//读取内容
while((len = fis.read(buf))!=-1){
out.write(buf,0,len);//写入socket流中
}
//结束
s.shutdownOutput();//结束标记
//服务端回复
InputStream in = s.getInputStream();
byte []bufIn = new byte[1024];
int num = in.read(bufIn);
System.out.println(new String(bufIn,0,num));
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
服务端:
public static void main(String args[]){
try {
//建立连接
ServerSocket ss = new ServerSocket(10002);
Socket s = ss.accept();
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip+"......conntected");
InputStream in = s.getInputStream();
FileOutputStream fos = new FileOutputStream("H:\\Pictures\\sa1.jpg");
byte []buf = new byte[1024];
int len = 0;
while((len = in.read(buf))!=-1){
fos.write(buf,0,len);//输出上传内容
}
OutputStream out = s.getOutputStream();
out.write("上传成功".getBytes());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
4.2 多线程上传图片
好了,分析单线程的图片上传程序可知:在服务端上传过程中读取上传图片部分属于共性部分代码,需要使用多线程操作。
新建PicThread类实现Runnable接口,用以支持多线程上传。
代码如下:
public class PicThread implements Runnable{
private Socket s;
PicThread(Socket s){
this.s = s;
}
@Override
public void run() {
int count = 1;
String ip = s.getInetAddress().getHostAddress();
try {
InputStream in = s.getInputStream();
//小代码,实现文件时,多文件的命名
File file = new File(ip+"("+(count)+")"+".jpg");
//遍历,直到文件编号不冲突。
while(file.exists()){
file = new File(ip+"("+(count++)+")"+".jpg");
}
FileOutputStream fos = new FileOutputStream(file);
byte []buf = new byte[1024];
int len = 0;
while((len = in.read(buf))!=-1){
fos.write(buf,0,len);
}
OutputStream out = s.getOutputStream();
out.write("上传成功".getBytes());
} catch (Exception e) {
throw new RuntimeException(ip+"....error");
}
}
}
服务端代码调整
public static void main(String args[]){
try {
ServerSocket ss = new ServerSocket(10002);
//阻塞式方法,循环读取,有文件上传,便不会关闭
while(true){
Socket s = ss.accept();
new Thread(new PicThread(s)).start();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
为了上传的方便,在客户端也需要做条件的维护。
public static void main(String args[]){
try {
File file = new File(args[0]);
if(!(file.exists() && file.isFile())){
return;
}
if(!file.getName().endsWith(".jpg")){
return;
}
if(file.length()>1024*1024*5){
return;
}
Socket s = new Socket("192.168.0.109",10002);
FileInputStream fis = new FileInputStream(file);
OutputStream out = s.getOutputStream();
byte []buf = new byte[1024];
int len = 0;
while((len = fis.read(buf))!=-1){
out.write(buf,0,len);//写入socket流中
}
s.shutdownOutput();//结束标记
InputStream in = s.getInputStream();
byte []bufIn = new byte[1024];
int num = in.read(bufIn);
System.out.println(new String(bufIn,0,num));
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
1 启动服务端,等待。
2 启动客户端,上传图片。
通过这段代码,即可实现多线程上传图片,即多用户并发上传图片。
END
网友评论