通信架构分为两种:CS架构(客户端/服务器),BS架构(浏览器/服务器)
cs架构:
bs架构:
1.ip,设备的唯一标识
2.端口号,程序的id标识
3.协议,连接和数据传输的规则
TCP协议
可靠连接:确定通信双方,收发消息都是正常无问题的(全双工通信)
//
1.将传输的字符放入字节数组(getbytes方法,将字符串转为字节)
2.传入的字节长度
3.接收端的ip地址
4.接收端的端口号
public DatagramPacket(byte[] buf,int length,InetAddress address, int port)
消息通信,一发一收实现步骤
客户端
服务端
消息通信,多发多收实现步骤
//服务端
public class UdpSocketServer {
public static void main(String[] args) throws IOException {
/**
* UDP不可靠通信,服务器
*/
DatagramSocket datagramSocket = new DatagramSocket(9000);//申明一个服务器对象
byte[]bytes=new byte[1024*64];
DatagramPacket datagramPacket=new DatagramPacket(bytes,bytes.length);//申明一个容器用于接收传输过来的数据
while(true)
{
datagramSocket.receive(datagramPacket);//服务器对象接收容器的类容
String str=new String(bytes,0,datagramPacket.getLength());//将字节数组转换成字符串
System.out.println(str);
}
}
}
//客户端
public class UdpSocketConsumer {
public static void main(String[] args) throws Exception {
Scanner scanner=new Scanner(System.in);
while (true)
{
System.out.println("开始输入吧!");
String str = scanner.nextLine();//将传输的数据转换成字节数组
if (str.equals("exit"))
{
break;
}
byte[] bytes = str.getBytes();
DatagramSocket datagramSocket=new DatagramSocket();//申明一个客户端对象
DatagramPacket datagramPacket=new DatagramPacket(bytes,bytes.length, InetAddress.getLocalHost(),9000);//用于存储传输数据,长度,ip,端口
datagramSocket.send(datagramPacket);//发送消息
}
}
}
特点:面向连接,可靠通信
TCP通信的步骤
服务端
客户端
必须将接收到的socket对象交给多个线程管理
聊天室多人通信—cs架构
//客户端,负责向服务器发送消息,服务器转发给其他线程
public class TCPSocketConsumer {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1", 8999);
new TCPSocketConsumerThead(socket).start();
OutputStream outputStream = socket.getOutputStream();
DataOutputStream dos = new DataOutputStream(outputStream);
Scanner sc=new Scanner(System.in);
System.out.println("服务已经启动,开始聊天");
while (true)
{
String line = sc.nextLine();
if (line.equals("exit"))
{
socket.close();
outputStream.close();
break;
}
dos.writeUTF(line);
}
}
}
//客户端线程,负责接收服务端的消息,看到关于自己的线程信息
public class TCPSocketConsumerThead extends Thread{
private Socket socket;
public TCPSocketConsumerThead(Socket socket)
{
this.socket=socket;
}
@Override
public void run() {
try {
InputStream inputStream = socket.getInputStream();
DataInputStream dataInputStream = new DataInputStream(inputStream);
while(true)
{
try {
String s = dataInputStream.readUTF();
System.out.println(s);
} catch (Exception e) {
}
}
} catch (IOException e) {
System.out.println("自己下线了");
}
}
}
//服务端,负责接收客户端的消息
public class TCPSocketServer {
public static List<Socket> sockets=new ArrayList<>();
public static void main(String[] args) throws Exception {
System.out.println("------服务端启动-----");
ServerSocket serverSocket = new ServerSocket(8999);
while (true)
{
Socket accept = serverSocket.accept();
sockets.add(accept);
System.out.println(accept.getInetAddress()+"已经上线");
TcpSocketServerThead thead=new TcpSocketServerThead(accept);
thead.start();
}
}
}
//服务端线程,负责将服务端接收到的信息传递给其他客户端线程
public class TcpSocketServerThead extends Thread{
private Socket socket;
private DataInputStream dataInputStream;
public TcpSocketServerThead(Socket socket) {
this.socket=socket;
}
@Override
public void run()
{
while(true){ try
{
InputStream inputStream = socket.getInputStream();
dataInputStream = new DataInputStream(inputStream);
String s = dataInputStream.readUTF(dataInputStream);
transAll(s);
System.out.println(s);
} catch (Exception e) {
System.out.println(socket.getInetAddress()+"已经下线");
TCPSocketServer.sockets.remove(socket);
try {
socket.close();
dataInputStream.close();
break;
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
}}
public void transAll(String msg) throws IOException
{
for(Socket s:TCPSocketServer.sockets)
{
OutputStream outputStream = s.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
dataOutputStream.writeUTF(msg);
dataOutputStream.flush();
}
}
}
BS架构
//之开发服务端,通过网页通信
public class BSSocket {
public static void main(String[] args) throws IOException {
System.out.println("------服务端启动-----");
ServerSocket serverSocket = new ServerSocket(8999);
while (true)
{
Socket accept = serverSocket.accept();
System.out.println(accept.getInetAddress()+"已经上线");
BSSocketThread bsSocketThread=new BSSocketThread(accept);
bsSocketThread.start();
}
}
}
//线程
public class BSSocketThread extends Thread{
private Socket socket;
public BSSocketThread(Socket socket)
{
this.socket=socket;
}
@Override
public void run() {
try {
OutputStream outputStream = socket.getOutputStream();
PrintStream printStream=new PrintStream(outputStream);
printStream.println("HTTP/1.1 200 OK");
printStream.println("Content-Type:text/html;charset=UTF-8");
printStream.println();
printStream.println("程序员666");
printStream.close();
socket.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
使用BS架构实现通信的话,必须遵守HTTP协议
如果每次访问都创建一个线程,如果并发很高的话,就可能实现宕机。需要使用线程池