——- android培训、java培训、期待与您交流! ———-
1.1 TCP
1.1.1 文字发送 Demo
服务端:
package com.test.blog5;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
public class ServerDemo {
public static void main(String[] args) throws IOException {
// 创建服务端对象
ServerSocket ss = new ServerSocket(10002);
// 获取连接过来的客户端对象。
Socket s = ss.accept();// 阻塞式
// String ip = s.getInetAddress().getHostAddress();
// 通过 socket 对象获取输入流,要读取客户端发来的数据。
InputStream in = s.getInputStream();
byte[] buf = new byte[24];
// int len = in.read(buf);
int len = 0;
// String text = new String(buf,0,len);
// System.out.println(ip + ":" + text);
StringBuilder sb = new StringBuilder();
while ((len = in.read(buf)) != -1) {
// sb.append(new String(buf, 0, len));
System.out.println("服务端接收到数据:" + new String(buf, 0, len));
}
s.close();
ss.close();
}
}
客户端:
package com.test.blog5;
import java.net.Socket;
import java.io.OutputStream;
import java.io.IOException;
import java.net.UnknownHostException;
import java.io.InputStream;
public class ClientDemo {
public static void main(String[] args) throws UnknownHostException,
IOException {
// 创建客户端socket服务。
Socket socket = new Socket("127.0.0.1", 10002);
// 获取socket流中的输出流
OutputStream out = socket.getOutputStream();
// 使用输出流将指定的数据写出去。
out.write("TCP客户端发送数据".getBytes());
// 断开链接,关闭资源,socket获取的输出流也被关闭,没有必要再写代码关闭
socket.close();
}
}
启动服务端,然后启动客户端,运行结果:
1.1.2 交互Demo
发送端发送数据,服务端收到后返回数据
服务端:
package com.test.blog5;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
public class ServerDemo {
public static void main(String[] args) throws IOException {
// 创建服务端对象
ServerSocket ss = new ServerSocket(10002);
// 获取连接过来的客户端对象。
Socket s = ss.accept();// 阻塞式
// String ip = s.getInetAddress().getHostAddress();
// 通过 socket 对象获取输入流,要读取客户端发来的数据。
InputStream in = s.getInputStream();
byte[] buf = new byte[24];
// int len = in.read(buf);
int len = 0;
// String text = new String(buf,0,len);
// System.out.println(ip + ":" + text);
// StringBuilder sb = new StringBuilder();
while ((len = in.read(buf)) != -1) {
// sb.append(new String(buf, 0, len));
System.out.println("服务端接收到数据:" + new String(buf, 0, len));
}
// 使用客户端socket对象的输出流给客户端返回数据
OutputStream out = s.getOutputStream();
out.write("收到".getBytes());
s.close();
ss.close();
}
}
客户端:
package com.test.blog5;
import java.net.Socket;
import java.io.OutputStream;
import java.io.IOException;
import java.net.UnknownHostException;
import java.io.InputStream;
public class ClientDemo {
public static void main(String[] args) throws UnknownHostException,
IOException {
// 创建客户端socket服务。
Socket socket = new Socket("127.0.0.1", 10002);
// 获取socket流中的输出流
OutputStream out = socket.getOutputStream();
// 使用输出流将指定的数据写出去。
out.write("TCP客户端发送数据".getBytes());
socket.shutdownOutput();// 重要,告诉服务端发送完毕
// 读取客户端返回的数据,使用Socket读取流。
InputStream in = socket.getInputStream();
byte[] buf = new byte[1024];
int len = in.read(buf);
String text = new String(buf, 0, len);
System.out.println(text);
// 断开链接,关闭资源,socket获取的输出流也被关闭,没有必要再写代码关闭
socket.close();
}
}
运行结果:
1.1.3 上传图片到服务器
服务端:
package com.test.blog5;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class PicUploadServer {
private static String pic = "d:" + File.separator + "pics";
private static String picType = ".jpg";
/*
* TCP--图片上传服务端
*/
public static void main(String[] args) {
try {
System.out.println("图片服务端启动成功-----------");
ServerSocket ss = new ServerSocket(10006);
Socket s = ss.accept();
// 接收图片的目录路径
File dir = new File(pic);
if (!dir.exists()) {
dir.mkdir();
}
// 定义接收客户端发送数据的流,注意是图片,不是文本数据,所以不用write类的包装
InputStream is = s.getInputStream();
// 定义往服务端存储文件的流
FileOutputStream fos = new FileOutputStream(new File(dir,
System.currentTimeMillis() + picType));
// 定义读取数据缓冲区
byte[] buf = new byte[1024];
int len = 0;
// 将数据写入
while ((len = is.read(buf)) != -1) {
fos.write(buf, 0, len);
}
// 给客户端返回信息
PrintWriter pw = new PrintWriter(new OutputStreamWriter(
s.getOutputStream()), true);
pw.println("上传图片成功");
is.close();
fos.close();
s.close();
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端
package com.test.blog5;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class PicUploadClient {
/*
* TCP--图片上传客户端
*/
public static void main(String[] args) {
try {
System.out.println("图片客户端启动成功-----------");
Socket s = new Socket("127.0.0.1", 10006);
OutputStream os = s.getOutputStream();
File file = new File("d:\\3.jpg");
if (!file.exists()) {
throw new FileNotFoundException("文件不存在");
}
// 定义原始数据流
FileInputStream fis = new FileInputStream(file);
// 定义数据缓冲区
byte[] buf = new byte[1024];
int len = 0;
while ((len = fis.read(buf)) != -1) {
os.write(buf, 0, len);
}
s.shutdownOutput();// 重要,告诉服务端发送完毕,否则会出现死等现象
// 拿到客户端的读入流
BufferedReader br = new BufferedReader(new InputStreamReader(
s.getInputStream()));
// 读取服务端返回信息
String result = br.readLine();
System.out.println("结果:" + result);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果:
1.1.4 上传文本到服务器
服务端:
package com.test.blog5;
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class UploadServer {
/*
* 上传文本文件服务端
*/
public static void main(String[] args) {
ServerSocket ss;
try {
System.out.println("服务端启动成功-----------");
ss = new ServerSocket(10005);
Socket s = ss.accept();
System.out.println(s.getInetAddress().getHostAddress() + "链接成功");
// 定义读取客户端发送数据的流
BufferedReader br = new BufferedReader(new InputStreamReader(
s.getInputStream()));
// 定义往服务端存数据的流
PrintWriter pw = new PrintWriter(new FileOutputStream(
"d:\\upload.txt"), true);
// 定义给客户端返回信息的流
PrintWriter out = new PrintWriter(s.getOutputStream(), true);
// 开始接收客户端信息并写入到服务端文件
String line = "";
while ((line = br.readLine()) != null) {
System.out.println(line);
pw.write(line + "\r\n");
pw.flush();
}
// 保存完毕给客户端返回信息
out.println("上传成功!");
br.close();
pw.close();
out.close();
s.close();
ss.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
客户端:
package com.test.blog5;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class UploadClient {
/*
* 上传文本文件客户端
*/
public static void main(String[] args) {
try {
System.out.println("客户端启动成功-----------");
Socket s = new Socket("127.0.0.1", 10005);
// 定义读取源文件的流
BufferedReader br = new BufferedReader(new InputStreamReader(
new FileInputStream("d:\\out.txt")));
// 定义向服务端发送数据的流
PrintWriter out = new PrintWriter(new OutputStreamWriter(
s.getOutputStream()), true);
// 定义读取服务端返回信息的流
BufferedReader brin = new BufferedReader(new InputStreamReader(
s.getInputStream()));
String line = "";
while ((line = br.readLine()) != null) {
out.println(line);
}
//告诉服务端,客户端写完了,此步骤非常重要,不然服务端会阻塞一直在等待
s.shutdownOutput();
// 输出服务端返回的信息
System.out.println("服务端返回:" + brin.readLine());
br.close();
out.close();
s.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果:
1.2 总结
****TCP传输流程:
**客户端:
建立Socket服务,并制定要连接的主机和端口;
获取Socket流中的输出流OutputStream,将数据写入流中,通过网络发送给服务端;
获取Socket流中的输出流InputStream,获取服务端的反馈信息;
关闭资源。
**服务端:
建立ServerSocket服务,并监听一个端口;
通过ServerSocket服务的accept方法,获取Socket服务对象;
使用客户端对象的读取流获取客户端发送过来的数据;
通过客户端对象的写入流反馈信息给客户端;
关闭资源;
1.3 注意
- Tcp连接方式必须先启动服务端后启动发送端
- 客户端告诉服务端发送完毕,避免双方阻塞死等现象。可以使用约定的结束符来判定,但是不是最好的方法,推荐使用socket.shutdownOutput();
- 同时处理多个客户端使用多线程
- 对于同一个socket,如果关闭了输出流,则与该输出流关联的socket也会被关闭。所以一般不用关闭流,直接关闭socket就可以了