此次博客主要以代码为主,其中包含了丰富的注释
简单的tcp
简单介绍tcp是如何发送数据,以及接受数据
代码一:客户端
package com.net.tcp;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
/**
* TCP协议发送数据的步骤
* A:创建发送数据的socket对象。
* 创建对象的时候要指定目标主机和端口
* B:获取socket对象的输出流
* 是字节流还是字符流?字节流。
* C:写数据
* D:释放资源
*
* @author yuliyang
* @version $Id: ClientDemo.java, v 0.1 2016年11月23日 下午10:57:55 yuliyang Exp $
*/
public class ClientDemo {
public static void main(String[] args) throws IOException {
//A:创建发送数据的socket对象
//Socket(InetAddress address, int port)
//Socket(String host, int port)
//java.net.ConnectException: Connection refused: connect
//如果你先启动了客户端,发现如上错误,是因为服务端没有开启,TCP协议的程序,必须先开启服务器
Socket s = new Socket("192.168.31.222", 10086);
//B:获取socket对象的输出流
OutputStream os = s.getOutputStream();
//C:
os.write("hello write".getBytes());
//D:
os.close();
s.close();
}
}
代码一:服务端
package com.net.tcp;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* TCP协议接收数据的步骤
* A:创建接收数据的socket对象。
* 创建对象的时候要指定端口
* B:监听客户端连接,
* 等待客户端连接
* C:读数据,并显示在控制台
* D:释放资源
* 注意事项;服务器需要先开启
* @author yuliyang
* @version $Id: ClientDemo.java, v 0.1 2016年11月23日 下午10:57:55 yuliyang Exp $
*/
public class ServerDemo {
public static void main(String[] args) throws IOException {
//A:ServerSocket(int port)
ServerSocket serverSocket = new ServerSocket(10086);
//B:监听客户端连接
// Socket accept() 侦听并接受到此套接字的连接。
Socket s = serverSocket.accept();//此处为阻塞式方法
//C:获取socket对象的输入流,并读取数据
InputStream is = s.getInputStream();
byte[] buf = new byte[1024];
int len = is.read(buf);
//此处为解析收到的数据
String data = new String(buf, 0, len);
System.out.println("data" + data);
//D:释放资源
is.close();
serverSocket.close();
}
}
如果上面的代码你看懂了的话,那就接着继续玩耍吧。
代码二:客户端,新增获取了服务端返回的信息
package com.net.tcp2;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class ClientDemo {
public static void main(String[] args) throws IOException {
//创建客户端socket
Socket socket = new Socket("192.168.31.222", 12312);
/**
* 使用通道输出流写数据
*/
OutputStream outputStream = socket.getOutputStream();
outputStream.write("我是发送的".getBytes());
/**
* 使用通道输入流获取返回的消息
*/
InputStream inputStream = socket.getInputStream();
byte[] b = new byte[1024];
int len = inputStream.read(b);
String s = new String(b, 0, len);
System.out.println("客户端获取到的响应是:" + s);
socket.close();
}
}
代码二:服务端
package com.net.tcp2;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(12312);
Socket s = serverSocket.accept();
InputStream inputStream = s.getInputStream();
byte[] buf = new byte[1024];
int len = inputStream.read(buf);
String data = new String(buf, 0, len);
System.out.println("服务端获取到的数据是:" + data);
/**
* 使用通道返回响应,告诉客户端结果
*/
OutputStream outputStream = s.getOutputStream();
outputStream.write("我接收到了".getBytes());
//释放资源
serverSocket.close();
inputStream.close();
outputStream.close();
}
}
代码三:客户端 新增需求:看注释
、
package com.net.tcp3;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
/**
* 需求:把发送的数据改进为来自键盘录入,
* 客户端发送数据用键盘录入,服务端把数据显示即可
*
* @author yuliyang
* @version $Id: ClientDemo.java, v 0.1 2016年11月24日 下午9:08:14 yuliyang Exp $
*/
public class ClientDemo {
public static void main(String[] args) throws IOException {
Socket s = new Socket("192.168.31.222", 10010);
//读取键盘录入的数据
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//封装:将通道内的输出字节流转化为字符流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line = null;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
s.close();
}
}
代码三:服务端
package com.net.tcp3;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(10010);
Socket s = serverSocket.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
String line = null;
while ((line = br.readLine()) != null) {
System.out.println("接收的数据为:" + line);
}
//释放资源
s.close();
serverSocket.close();
}
}
代码四:客户端
需求:服务端需要将从客户端获取的资源写入到文件中
package com.net.tcp5;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
public class ClientDemo {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("192.168.31.222", 10086);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = null;
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
socket.close();
}
}
代码四:服务端
package com.net.tcp5;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
//创建服务器socket对象
ServerSocket serverSocket = new ServerSocket(10086);
//监听客户端连接
Socket socket = serverSocket.accept();//阻塞式
//封装通道内的输入流
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//将数据写入到文件中
BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\a.txt"));
String line = null;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
bw.close();
serverSocket.close();
}
}
代码五:客户端
需求:客户端读取本地文件,并传送给服务端,服务端收到文件之后,并copy一份
package com.net.tcp6;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
public class ClientDemo {
public static void main(String[] args) throws IOException {
//创建客户端的对象
Socket s = new Socket("192.168.31.222", 10086);
//读取文件的数据
BufferedReader br = new BufferedReader(new FileReader("InetAddressDemo.java"));
//把通道的输出流包装
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line = null;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
s.close();
br.close();
}
}
代码五:服务端
package com.net.tcp6;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
//创建服务器对象
ServerSocket serverSocket = new ServerSocket(10086);
//监听客户端连接
Socket s = serverSocket.accept();
//把通道内的输入流封装一下
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
//把输入流输出到文件
BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.txt"));
String line = null;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
serverSocket.close();
bw.close();
}
}
代码六:客户端
需求:在文件接收完成之后,服务器需要通知客户端,文件接收完成
问题:会因为阻塞式,导致接收不到反馈消息
解决方案:A:自定义结束标签
B:使用socket自带的方法
此处只展现socket自带方案
package com.net.tcp7;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
/**
* 我把文件发给你了,你没有告诉我文件你是否收到文件
* 需要服务端给我一个反馈
*
* @author yuliyang
* @version $Id: ClientDemo.java, v 0.1 2016年11月24日 下午10:21:16 yuliyang Exp $
*/
public class ClientDemo {
public static void main(String[] args) throws IOException {
//创建客户端的对象
Socket s = new Socket("192.168.31.222", 10086);
//读取文件的数据
BufferedReader br = new BufferedReader(new FileReader("InetAddressDemo.java"));
//把通道的输出流包装
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line = null;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
/**
* 接收从服务端返回的信息
* 此处发现无法进行到这里,由于服务端阻塞,
* 因为服务器无法判断我们之前的数据是否已经传输完毕,
* 此时socket提供了一个方法:
* shutdownOutput
* 禁用输出流 方法
*/
s.shutdownOutput();
BufferedReader infoByServer = new BufferedReader(new InputStreamReader(s.getInputStream()));
String data = infoByServer.readLine();//阻塞式
System.out.println("client" + data);
s.close();
br.close();
}
}
代码六:服务端
package com.net.tcp7;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 收到文件之后,给客户端一个反馈
*
* @author yuliyang
* @version $Id: ServerDemo.java, v 0.1 2016年11月24日 下午10:22:00 yuliyang Exp $
*/
public class ServerDemo {
public static void main(String[] args) throws IOException {
//创建服务器对象
ServerSocket serverSocket = new ServerSocket(10086);
//监听客户端连接
Socket s = serverSocket.accept();
//把通道内的输入流封装一下
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
//把输入流输出到文件
BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.txt"));
String line = null;
while ((line = br.readLine()) != null) {//阻塞式
bw.write(line);
bw.newLine();
bw.flush();
}
/**
* 新增反馈
* 从通道将反馈返回回去
*/
BufferedWriter feadback = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
feadback.write("数据接收成功了");
feadback.newLine();
feadback.flush();
serverSocket.close();
bw.close();
}
}