1.UDP服务端和客户端 “一对一” 和“ 多对多” 传送和接收信息
- 一对一
import org.junit.Test;
import java.net.*;
public class TestUdp {
//服务端
@Test
public void serverTest() throws Exception {
DatagramSocket socket=new DatagramSocket(8888);
//创建一个数据包对象接收数据
byte[] buffer=new byte[1024*64];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
//等待接收数据
socket.receive(packet);
//取出数据
int len = packet.getLength();
String rs = new String(buffer,0,len);
System.out.println(rs);
socket.close();
}
//客户端
@Test
public void clientTest() throws Exception {
//创建发送对象(人)
DatagramSocket socket = new DatagramSocket();
//创建一个数据包对象封装数据
byte[] buffer="我是一个快乐的韭菜盒子".getBytes();
DatagramPacket packet=new DatagramPacket(buffer,buffer.length, InetAddress.getLocalHost(),8888);
//3。发送数据
socket.send(packet);
socket.close();
}
}
- 多对多(组播)
import org.junit.Test;
import java.net.*;
import java.util.Scanner;
//测试组播
public class TestUdpgroupBrocastt {
//服务端
@Test
public void serverTest() throws Exception {
// DatagramSocket socket=new DatagramSocket(8888);
//创建一个组播对象接口
MulticastSocket socket=new MulticastSocket(9999);
//把当前接收端加到一个组播组中,绑定对应的组播消息的组播IP
//joinGroup(SocketAddress mcastaddr, NetworkInterface netIf)
socket.joinGroup(new InetSocketAddress(InetAddress.getByName("224.0.1.1"),9999),
NetworkInterface.getByInetAddress(InetAddress.getLocalHost()));
//创建一个数据包对象接收数据
byte[] buffer=new byte[1024*64];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
while (true) {
//等待接收数据
socket.receive(packet);
//取出数据
int len = packet.getLength();
String rs = new String(buffer,0,len);
System.out.println(rs);
//获取发送端的IP和端口
System.out.println("收到了来自:"+packet.getAddress()+",对方接口是:"+packet.getPort()+"的消息:"+rs);
}
// socket.close();
}
//客户端
@Test
public void clientTest() throws Exception {
//创建发送对象(人)
DatagramSocket socket = new DatagramSocket();
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("请输入内容:");
String msg = sc.nextLine();
if("exit".equals(msg)){
socket.close();
return;
}
//创建一个数据包对象封装数据
byte[] buffer=msg.getBytes();
DatagramPacket packet=new DatagramPacket(buffer,buffer.length,InetAddress.getByName("224.0.1.1"),9999);
//3。发送数据
socket.send(packet);
}
}
}
- TCP通信
//基础通信(存在的问题:当服务端接收不到数据就会报连接异常)
import org.junit.Test;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class TestTcp {
@Test
public void client() throws Exception{
//1.创建socket接口
Socket socket = new Socket("127.0.0.1",7777);
//2.从socket通信管道中得到一个字节输出流,负责发送给数据
OutputStream os = socket.getOutputStream();
//3.把低级的字节流包装成打印流
PrintStream ps = new PrintStream(os);
//4.发送消息
ps.println("我是TCP 客户端,你要一起玩吗?");
ps.flush();
}
@Test
public void server() throws IOException {
//1.注册接口
ServerSocket sserverocket = new ServerSocket(7777);
//2.必须调用accept接口,,等待客户端的socket连接请求
Socket socket = sserverocket.accept();
//3.从socket中得到一个字节输入流
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//3.按行读取数据
String msg;
if((msg= br.readLine())!=null){
System.out.println(socket.getRemoteSocketAddress()+"说了:"+msg);
}
}
}
- TCP通信-多发多收消息
待解决问题:1.目前服务端是单线程的,每次只能处理一个客户端的消息。(加入一个循环)
2.客户端的端口只有一个(解决方式如下图)
package com.practies;
import org.junit.Test;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class TestThreadTcp {
@Test
public void client() throws IOException {
Socket socket = new Socket("127.0.0.1",7777);
OutputStream os = socket.getOutputStream();
PrintStream ps = new PrintStream(os);
Scanner sc = new Scanner(System.in);
while (true){
System.out.println("请说:");
String msg = sc.nextLine();
ps.println(msg);
ps.flush();
}
//关闭端口
///socket.close();
}
@Test
public void server(){
try {
System.out.println("服务器启动成功");
ServerSocket ss=new ServerSocket(7777);
while(true){
//从socket管道接受数据
Socket socket= ss.accept();
//创建线程开始处理
new ServerReaderThread(socket).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//创建线程方法
public class ServerReaderThread extends Thread{
private Socket socket;
public ServerReaderThread(Socket socket){
this.socket=socket;
}
@Override
public void run() {
try {
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String msg;
while ((msg=br.readLine())!=null){
System.out.println(socket.getRemoteSocketAddress()+"说了:"+msg);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
- 上述代码存在的问题:当客户端反复发送数据时,服务端会一直创建线程,线程太多时,会占用系统cpu、资源等等,因此引入线程池
package com.practies;
import org.junit.Test;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.*;
public class TestThreadTcp2 {
private static ExecutorService pool = new ThreadPoolExecutor(3,5,
6, TimeUnit.SECONDS,new ArrayBlockingQueue<>(2),
Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
@Test
public void client() throws IOException {
Socket socket = new Socket("127.0.0.1",7777);
OutputStream os = socket.getOutputStream();
PrintStream ps = new PrintStream(os);
Scanner sc = new Scanner(System.in);
while (true){
System.out.println("请说:");
String msg = sc.nextLine();
ps.println(msg);
ps.flush();
}
//关闭端口
///socket.close();
}
@Test
public void server(){
//使用一个静态变量记住一个线程池对象
try {
System.out.println("服务器启动成功");
ServerSocket ss=new ServerSocket(7777);
while(true){
//从socket管道接受数据
Socket socket= ss.accept();
//创建线程开始处理
System.out.println(socket.getRemoteSocketAddress()+"它来了,上线了!");
Runnable target = new ServerReadRunnable(socket);
pool.execute(target);
}
} catch (IOException e) {
e.printStackTrace();
}
}
//创建线程方法
public class ServerReadRunnable implements Runnable {
private Socket socket;
public ServerReadRunnable(Socket socket){
this.socket=socket;
}
@Override
public void run() {
try {
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String msg;
while ((msg=br.readLine())!=null){
System.out.println(socket.getRemoteSocketAddress()+"说了:"+msg);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
- TCP通信实战-即时通信(类似弹幕)
import org.junit.Test;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.*;
public class TestThreadTcp3 {
//定义一个静态的list集合存储当前全部在线的socket
public static List<Socket> allOnlineSockets= new ArrayList<Socket>();
@Test
public void client() throws IOException {
Socket socket = new Socket("127.0.0.1",7777);
//创建一个独立的线程负责这个客户端的读消息
new ClientReadThread(socket).start();
OutputStream os = socket.getOutputStream();
PrintStream ps = new PrintStream(os);
Scanner sc = new Scanner(System.in);
while (true){
System.out.println("请说:");
String msg = sc.nextLine();
ps.println(msg);
ps.flush();
}
//关闭端口
///socket.close();
}
@Test
public void server(){
try {
System.out.println("服务器启动成功");
ServerSocket ss=new ServerSocket(7777);
while(true){
//从socket管道接受数据
Socket socket= ss.accept();
allOnlineSockets.add(socket);
//创建线程开始处理
new ServerReaderThread(socket).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//创建线程方法
public class ServerReaderThread extends Thread{
private Socket socket;
public ServerReaderThread(Socket socket){
this.socket=socket;
}
@Override
public void run() {
try {
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String msg;
while ((msg=br.readLine())!=null){
System.out.println(socket.getRemoteSocketAddress()+"说了:"+msg);
//把消息发给全部的管道
sendMsgtoAll(msg);
}
} catch (IOException e) {
System.out.println(socket.getRemoteSocketAddress()+",下线了,下次再来哦");
allOnlineSockets.remove(socket);
}
}
}
public void sendMsgtoAll(String msg ) throws IOException {
for (Socket socket : allOnlineSockets) {
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println(msg);
ps.flush();
}
}
public class ClientReadThread extends Thread {
private Socket socket;
public ClientReadThread(Socket socket){
this.socket=socket;
}
@Override
public void run() {
try {
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String msg;
while ((msg=br.readLine())!=null){
System.out.println("收到消息了。。。。。"+msg);
}
} catch (IOException e) {
System.out.println("服务端把你踢出去了");
}
}
}
}
- BS
(1)、之前的客户端都是什么样的 。其实就是CS架构,客户端实需要我们自己开发实现的。
(2)、BS结构是什么样的,需要开发客户端吗? 浏览器访问服务端,不需要开发客户端。
package com.practies;
import org.junit.Test;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class BSServerTest {
@Test
public void server(){
try {
System.out.println("服务器启动成功");
ServerSocket ss=new ServerSocket(7777);
while(true){
//从socket管道接受数据
Socket socket= ss.accept();
//创建线程开始处理
new ServerReaderThread(socket).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//创建线程方法
public class ServerReaderThread extends Thread{
private Socket socket;
public ServerReaderThread(Socket socket){
this.socket=socket;
}
@Override
public void run() {
try {
PrintStream ps = new PrintStream(socket.getOutputStream());
//响应HTTP格式
ps.println("HTTP/1.1 200 OK");
ps.println("Content-Type:text/html;charset=UTF-8");
ps.println();//按照HTTP要求必须发一个空行
ps.println("<span style='color:red;font-size:90px'>哈哈</span>");
ps.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
package com.practies;
import org.junit.Test;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.*;
public class BSServerTest2 {
private static ExecutorService pool = new ThreadPoolExecutor(3,5,
6, TimeUnit.SECONDS,new ArrayBlockingQueue<>(2),
Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
@Test
public void server(){
//使用一个静态变量记住一个线程池对象
try {
System.out.println("服务器启动成功");
ServerSocket ss=new ServerSocket(7777);
while(true){
//从socket管道接受数据
Socket socket= ss.accept();
//创建线程开始处理
System.out.println(socket.getRemoteSocketAddress()+"它来了,上线了!");
Runnable target = new ServerReadRunnable(socket);
pool.execute(target);
}
} catch (IOException e) {
e.printStackTrace();
}
}
//创建线程方法
public class ServerReadRunnable implements Runnable {
private Socket socket;
public ServerReadRunnable(Socket socket){
this.socket=socket;
}
@Override
public void run() {
try {
PrintStream ps = new PrintStream(socket.getOutputStream());
//响应HTTP格式
ps.println("HTTP/1.1 200 OK");
ps.println("Content-Type:text/html;charset=UTF-8");
ps.println();//按照HTTP要求必须发一个空行
ps.println("<span style='color:red;font-size:90px'>哈哈</span>");
ps.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}