来来来,今天这篇博客,手把手教会你如何写一个在线聊天室,还学不会你来砍我
实现两个用户之间的在线交流,没有群组功能。
键盘输入
控制台输出
//发送方法实现类
package main.UdpChat;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.*;
public class SendMessage implements Runnable {
//主要看run方法
public int port;//自己的端口名
public int toPort;//发送到哪个端口
public String toIp;//发送到哪个地址
public DatagramSocket socket = null;
public BufferedReader reader = null;
public SendMessage(int port, int toPort, String toIp) {
this.port = port;
this.toPort = toPort;
this.toIp = toIp;
try {
socket = new DatagramSocket(curport);
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
//发送端
while(true)//不停的发
{
try {
reader = new BufferedReader(new InputStreamReader(System.in));
String data = reader.readLine();//获取输入,注意这里data最后没有\n,键盘中输入的是什么就是什么。 这里键盘输入是阻塞式输入,当没有输入的时候会在这里等待,不会向下执行。
byte[] datas = data.getBytes();
DatagramPacket packet = new DatagramPacket(datas,0,datas.length,
new InetSocketAddress(toIp,toPort));//打包
socket.send(packet);//发送 注意哦!这里send的是packet,和Tcp不同!!!
if(data.equals("bye"))
break;
}catch (Exception e)
{
System.out.println(e.getStackTrace());
}
}
socket.close();//关闭
}
}
//接收方法实现类
package main.UdpChat;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class ReceiveMessage implements Runnable {
public int port;//自己的端口
public DatagramSocket socket = null;
public String who;//谁发给我的?
public ReceiveMessage(int port,String who) {
this.port = port;
this.who = who;
try {
socket = new DatagramSocket(port);
} catch (SocketException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true)
{
try {
byte[] container = new byte[1024];
DatagramPacket packet = new DatagramPacket(container, 0, container.length);//打包
socket.receive(packet);//接收数据
byte[] data = packet.getData();
String receivedata = new String(data,0,data.length);
System.out.println(who + " :" +receivedata);//打印数据
if(receivedata.equals("bye"))
break;
}catch (Exception e)
{
System.out.println(e.getStackTrace());
}
}
socket.close();
}
}
创建完方法类后我们要建立用户了,让用户去使用这两个类中的run方法
//创建用户A
package main.UdpChat;
public class AChat {
public static void main(String[] args) {
//新建线程,当cpu有空闲时间的时候就执行
//新建发送功能,自己是7777端口,发送到localhost的8888端口
new Thread(new SendMessage(7777,8888,"localhost")).start();
//新建监听接收功能,监听来自9999端口的信息,同时认定该端口是B连接的地方。
new Thread(new ReceiveMessage(9999,"B")).start();
}
}
//创建用户B
package main.UdpChat;
public class BChat {
public static void main(String[] args) {
//和A同理。自己的端口是5555,发送到localhost的9999
new Thread(new SendMessage(5555,9999,"localhost")).start();
//监听着来自端口8888的信息,并认定该端口连接的是A
new Thread(new ReceiveMessage(8888,"A")).start();
}
}
启动AChat和BChat:
亮着两个小绿点表示启动完成。
效果:
以上就是UDP的实现方式,主要实现思路来源于狂神说!
//Send方法实现类
package main.Tcp;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;
public class SendMsg implements Runnable{
private String toIp;//发送到的地址
private int toPort;//发送到的端口
private Socket socket;//发送端
private OutputStream os;//io流
public SendMsg(String toIp, int toPort) {
this.toIp = toIp;
this.toPort = toPort;
try {
socket = new Socket(toIp,toPort);
os = socket.getOutputStream();
os.write("连接成功\n".getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true)
{
try {
Scanner sc = new Scanner(System.in);
String data = sc.nextLine() + "\n";//键盘输入,阻塞式,没有输入的时候就会在这里等待。这里必须加换行符,要不然接收端没法从缓存中写出来,因为使用的是BufferedReader类的readline方法,该方法只有读取到\n的时候才会从缓存中输出。
if(data.equals("bye"))//如果输入bye,那么断开连接。
break;
os.write(data.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
try {
os.close();
socket.close();
}catch (Exception e){
System.out.println(e.getMessage());
}
}
}
//Receive 接收端的方法实现类
package main.Tcp;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class Receive implements Runnable {
private int port;//当前端口
private String from;//从哪里来
private ServerSocket serverSocket;//服务端
private Socket socket;//从服务端接收到的客户端
private BufferedReader br;//流
public Receive(int port, String from) {
this.port = port;
this.from = from;
try {
serverSocket = new ServerSocket(port);
socket = serverSocket.accept();//连接只需要建立一次就行
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
@Override
public void run() {
String data = null;
while (true) {
try {
data = br.readLine();//将缓冲流中的数据读出来 注意!!!这里因为使用了ReadLine,所以只有遇到换行或者终止符的时候才停止写入到缓存中,所以我们在发送端的每一句话最后都加入了换行符。
System.out.println(from +" :" + data);
if(data == "bye")
break;
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
try {
socket.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//用户A
package main.Tcp;
public class A {
public static void main(String[] args) {
//注意要有start方法
//监听来自8888,用户B的信息
new Thread(new Receive(8888,"用户B")).start();
//将信息通过localhost发送到9999端口上
new Thread(new SendMsg("localhost",9999)).start();
}
}
//用户B
package main.Tcp;
import java.util.TreeMap;
public class B {
public static void main(String[] args) {
new Thread(new SendMsg("127.0.0.1",8888)).start();
new Thread(new Receive(9999,"用户A")).start();
}
}
初始化
执行结果
//UDP只能发送
package main.Udp;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;
import java.util.Scanner;
public class UdpClient {
public static void main(String[] args) throws IOException {
//发送端
int port = 8888;
DatagramSocket socket = new DatagramSocket(port);
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while(true)
{
try {
String data = reader.readLine();
byte[] datas = data.getBytes();
DatagramPacket packet = new DatagramPacket(datas,0,datas.length,
new InetSocketAddress("localhost",6666));
socket.send(packet);
if(data.equals("bye"))
break;
}catch (Exception e)
{
System.out.println(e.getStackTrace());
}
}
socket.close();
}
}
//UDP只接收
package main.Udp;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class UdpServer {
public static void main(String[] args) throws IOException {
int port = 6666;
DatagramSocket socket = new DatagramSocket(port);
while (true)
{
try {
byte[] container = new byte[1024];
DatagramPacket packet = new DatagramPacket(container, 0, container.length);
socket.receive(packet);
byte[] data = packet.getData();
String receivedata = new String(data,0,data.length);
System.out.println("接收机:" + port+ " :" + receivedata);
if(receivedata.equals("bye"))
break;
}catch (Exception e)
{
System.out.println(e.getStackTrace());
}
}
socket.close();
}
}
//TCP的发送方法
package main.Tcp;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
public class TcpClient {
public static void main(String[] args) {
Socket client = null;
OutputStream outputStream = null;
try {
client = new Socket("localhost",9999);
outputStream = client.getOutputStream();
while (true)
{
String data = new BufferedReader(new InputStreamReader(System.in)).readLine();
if(data.equals("bye"))
{
outputStream.write(data.getBytes());
break;
}
outputStream.write((data+"\n").getBytes());
}
}
catch (IOException e)
{
e.printStackTrace();
}
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//TCP接收方法
package main.Tcp;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpServer {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
BufferedReader br = null;
try {
serverSocket = new ServerSocket(9999);
socket = serverSocket.accept();//阻塞式结构,只有建立了连接才会继续向下执行
while (true) {
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String data = null;
data = br.readLine();
if (data.equals("bye"))
{
System.out.println("连接断开!");
break;
}
System.out.println(data);
}
} catch (IOException e) {
e.printStackTrace();
}
try {
br.close();
socket.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}