TCP 通信 java实现
OSI ---- --TCP/IP
应用层— 应用层
表示层
会话层
传输层 —传输层
网络层 —IP层
链路层 —网络接口层
物理层
传输层利用下层网络层的IP协议实现了应用层程序点对点的通信,主要有两个传输层协议:TCP、UDP。
传输层与应用层之间用一个桥梁Socket连接,IP收到链路层传过来的数据经过网络层的处理后交给传输层,由于网络层的传输是不可靠的传输层要实现可靠传输就要实现一些协议这就是TCP,而UDP协议不对接收到的数据做处理,参照数据报里的端口信息与应用层Socket绑定的端口号对照,交付报文。
Socket:连接进程与TCP和UDP数据的桥梁
TCP协议:为通信进程建立一条可靠的信道,使用前要先建立三次握手,关闭后要双发都关闭,四次挥手,通信时将进程传递的数据拆分为大小相同的分组,传给对方。而TCP利用的是数据流,要将进程的字符流转变为网络层可以接受的字节流。
UDP:通信双方,将对方的IP地址和端口号写入要发送的数据里,传递给对方自己IP和端口号,而UDP不对数据报做处理,所以传输速度快,并且UDP不会拆封数据报,即一次可以传递大量内容。
TCP client:
public class click {
public static void main(String[] args) throws IOException {
int flag=0;
//TCP 客户端
Socket socketcilck = new Socket();
InetSocketAddress isa = new InetSocketAddress("localhost",9999);
socketcilck.connect(isa);
// 发送区
OutputStream output = socketcilck.getOutputStream();
OutputStreamWriter outsw = new OutputStreamWriter(output, StandardCharsets.UTF_8);
BufferedWriter writerclick = new BufferedWriter(outsw);
writerclick.write(flag+++":你好小名,我是小华\n");
writerclick.flush();
while(true){
// 接受区
InputStream input = socketcilck.getInputStream();
InputStreamReader inputsr = new InputStreamReader(input,StandardCharsets.UTF_8);
BufferedReader reader = new BufferedReader(inputsr);
String s = reader.readLine();
System.out.println(flag+++s+"<<<server");
System.out.println("-------");
// 发送区
s = null;
System.out.print(flag+++"click:>>>");
Scanner scanner = new Scanner(System.in);
s=scanner.nextLine();
writerclick.write(s+"\n");
writerclick.flush();
System.out.println("-------");
if(s.equals("eye")){
System.out.println("通话关闭");
break;
}
}
socketcilck.close();
}
}
TCP server:
public class Server {
public static void main(String[] args) throws IOException {
// TCP 服务器
int flag=0;
System.out.println("---主线程开始");
ServerSocket serverSocket = new ServerSocket();
InetSocketAddress isa = new InetSocketAddress(9999);
serverSocket.bind(isa);
while(true){
Socket socket = serverSocket.accept();
new Thread(){// 分线程处理建立连接的通信,主线程等待下一个TCP连接请求
@Override
public void run(){
int flag=0;
BufferedWriter writer = null;
BufferedReader reader = null;
System.out.println("---分线程开始");
while(true){
try {
// 接收区
// 将字节流变为字符流
reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));
String readers = reader.readLine();
System.out.println(flag+++readers+"<<<:click");
System.out.println("-------");
// 发送区
// 将字符流变为字节流,利用UTF-8编码
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(),StandardCharsets.UTF_8));
System.out.print(flag+++"server>>>");
Scanner scanner = new Scanner(System.in);
String writers = scanner.nextLine();
writer.write(writers+"\n");
//System.out.println("-----"+writers);
// flush:系统一般会等代缓冲区满了后才发送数据,而我们的一句话不可能让缓冲区满了,fulsh是让缓冲区发送数据
writer.flush();
System.out.println("-------");
if (readers.equals("eye")||writers.equals("eye")){
socket.close();
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("---分线程结束,通话关闭");
System.out.println("等待客户中。。");
}
}.start();
System.out.println("等待客户中。。");
}
}
}
UDP client:
public class client {
public static void main(String[] args) throws IOException {
// UDP 客户端
DatagramSocket datagramSocket = new DatagramSocket();
datagramSocket.connect(InetAddress.getByName("localhost"),9999);
datagramSocket.setSoTimeout(1000);// 设置超时时间
byte[] bytes = "hello".getBytes(StandardCharsets.UTF_8);// 接送数据的buffer
bytes = new byte[1024];
DatagramPacket datagramPacket = new DatagramPacket(bytes,bytes.length);
datagramPacket.setData("hello".getBytes(StandardCharsets.UTF_8));
// 以字节形式发送传递数据
// 发送buffer
//datagramPacket.setData();
datagramSocket.send(datagramPacket);
// 接受buffer
bytes = new byte[1024];
datagramPacket = new DatagramPacket(bytes,bytes.length);
datagramSocket.receive(datagramPacket);
String s = new String(datagramPacket.getData(),datagramPacket.getOffset(),datagramPacket.getLength(),StandardCharsets.UTF_8);
System.out.println(s);
datagramSocket.disconnect();
}
}
UDP server:
public class server {
public static void main(String[] args) throws IOException {
// UDP 服务器
DatagramSocket datagramSocket = new DatagramSocket(9999);
// 接受区
byte[] bytes = new byte[1024];
DatagramPacket datagramPacket = new DatagramPacket(bytes,bytes.length);
datagramSocket.receive(datagramPacket);
String s = new String(datagramPacket.getData(),datagramPacket.getOffset(),datagramPacket.getLength(), StandardCharsets.UTF_8);
System.out.println(s);
// 发送区
bytes ="ACK".getBytes(StandardCharsets.UTF_8);
datagramPacket.setData(bytes);
datagramSocket.send(datagramPacket);
}
}
参考文章:TCP
java Socket库