public class MulticastSocketTest implements Runnable
{
private static final String BROADCAST_IP="230.0.0.1";
public static final init BROADCAST_POST = 30000;
private static final int DATA_LEN =4096;
private MulticastSocket socket = null;
private InetAddress broadcastAddress = null;
private Scanner scan = null;
byte[] inBuff = new byte[DATA_LEN];
private DatagramPacket inPacket = new DatagramPacket(inBuff,inBuff.length);
private DatagramPacket outPacket = null;
public void init() throws IOException
{
try
{
socket = new MulticastSocket(BROADCAST_PORT);
broadcastAddress = InetAddress.getByName(BROADCAST_IP);
socket.joinGroup(broadcastAddress);
socket.setLoopbackMode(false);
outPacket = new DatagramPacket(new byte[0],0,broadcastAddress,BROADCAST_PORT);
new Thread(this).start();
scan = new Scanner(System.in);
while(scan.hasNextLine())
{
byte[] buff = scan.nextLine().getBytes();
outPacket.setData(buff);
socket.send(outPacket);
}
}
finally
{
socket.close();
}
}
public void run()
{
try
{
while(true)
{
socket.receive(inPacket);
System.out.println("聊天信息:"+new String(inBuff,0,inPacket.getLength()));
}
}
catch(IOException ex)
{
ex.printStackTrace();
try
{
if(socket != null)
{
socket.leaveGroup(broadcastAddress);
socket.close();
}
System.exit(1);
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException
{
new MulticastSocketTest().init();
}
}
public class UserInfo
{
private String icon;
private String name;
private SocketAddress address;
private in lost;
private ChatFrame chatFrame;
public UserInfo();
{
}
public UserInfo(String icon,String name,SocketAddress address,int lost)
{
this.icon = icon;
this.name = name;
this.address = address;
this.lost = lost;
}
public int hashCode()
{
return address.hashCode();
}
public boolean equals(Object obj)
{
if(obj != null && obj.getClass() == UserInfo.class)
{
return ((UserInfo)obj).getAddress().equals(address);
}
return false;
}
}
public class ComUtil
{
private static final String BROADCAST_IP="230.0.0.1";
public static final int BROADCAST_PORT = 30000;
private static final int DATA_LEN = 4096;
private MulticastSocket socket = null;
private DatagramSocket singleSocket = null;
private InetAddress broadcastAddress = null;
byte[] inBuff = new byte[DATA_LEN];
private DatagramPacket inPacket = new DatagramPacket(inBuff,inBuff.length);
private DatagramPacket outPacket = null;
private LanChat lanTalk;
public ComUtil(LanChat lanTalk) throws IOException,InterruptedException
{
this.lanTalk = lanTalk;
socket = new MulticastSocket(BROADCAST_PORT);
singleSocket = new DatagramSocket(BROADCAST_PORT + 1);
broadcastAddress = InetAddress.getByName(BROADCAST_IP);
socket.joinGroup(broadcastAddress);
socket.setLoopbackMode(false);
outPacket = new DatagramPacket(new byte[0],0,broadcastAddress,BROADCAST_PORT);
new ReadBroad().start();
Thread.sleep(1);
new ReadSingle().start();
}
public void broadCast(String msg)
{
try
{
byte[] buff = msg.getBytes();
outPacket.setData(buff);
socket.send(outPacket);
}
catch(IOException ex)
{
ex.printStackTrace();
if(socket != null)
{
socket.close();
}
JOptionPane.showMessageDialog(null,"发送信息异常,请确认30000端口空闲,且网络连接正常!","网络异常",JOptionPane.ERROR_MESSAGE);
System.exit(1);
}
}
public void sendSingle(String msg,SocketAddress dest)
{
try
{
byte[] buff = msg.getBytes();
DatagramPacket packet = new DatagramPacket(buff,buff.length,dest);
singleSocket.send(packet);
}
catch(IOException ex)
{
ex.printStackTrace();
if(singleSocket != null)
{
singleSocket.close();
}
JOptionPane.showMessageDialog(null,"发送信息异常,请确认30001端口空闲,且网络连接正常","网络异常",JOptionPane.ERROR_MESSAGE);
System.exit(1);
}
}
class ReadSingle extends Thread
{
byte[] singleBuff = new byte[DATA_LEN];
private DatagramPacket singlePacket = new DatagramPacket(singleBuff,singleBuff.length);
public void run()
{
while(true)
{
try
{
singleSocket.receive(singlePacket);
lanTalk.processMsg(singlePacket,true);
}
catch(IOException ex)
{
ex.printStackTrace();
if(singleSocket != null)
{
singleSocket.close();
}
JOptionPane.showMessageDialog(null,"接收信息异常,请确认30001端口空闲,且网络兰连接正常!","网络异常",JOptioniPane.ERROR_MESSAGE);
System.exit(1);
}
}
}
}
class ReadBroad extends Thread
{
public void run()
{
while(true)
{
try
{
socket.receive(inPacket);
String msg = new String(inBuff,0,inPacket.getLength());
if(msg.startsWith(YeekuProtocol.PRESENCE)&&msg.endsWith(YeekuProtocol.PRESENCE))
{
String userMsg = msg.substring(2,msg.length()-2);
String[] userInfo = userMsg.split(YeekuProtocol.SPLITTER);
UserInfo user = new UserInfo(userInfo[1],userInfo[0],inPacket.getSocketAddress(),0);
boolean addFlag = true;
ArrayList<Integer> delList = new ArrayList<Integer>();
for(int i = 1;i<lanTalk.getUserNum();i++)
{
UserInfo current = lanTalk.getUser(i);
current.setLost(current.getLost()+1);
if(current.equals(user))
{
current.setLost(0);
addFlag = false;
}
if(current.getLost() > 2)
{
delList.add(i);
}
}
for(int i=0;i<delList.size();i++)
{
lanTalk.removeUser(delList.get(i));
}
if(addFlag)
{
lanTalk.addUser(user);
}
}
else
{
lanTalk.processMsg(inPacket,false);
}
}
catch(IOExeption ex)
{
ex.printStackTrace();
if(socket != null)
{
socket.close();
}
JOptionPane.showMessageDialog(null,"接收信息异常,请确认30000端口空闲,且网络连接正常","网络异常",JOptionPane.ERROR_MESSAGE);
System.exit(1);
}
}
}
}
}
public class LanChat extends JFrame
{
private DefaultListModel listModel = new DefaultListModel();
private JList friendsList = new JList(listModel);
private DateFormat formatter = DateFormat.getDateTimeInstance();
public LanChat()
{
super("局域网聊天");
friendsList.setCellRenderer(new ImageCellRenderer());
listModel.addElement(new UserInfo("all","所有人",null,-2000));
friendsList.addMouseListener(new ChangeMusicListener());
add(new JScrollPane(friendsList));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(2,2,160.600);
}
public void addUser(UserInfo user)
{
listModel.addElement(user);
}
public viod removeUser(int pos)
{
listModel.removeElementAt(pos);
}
public UserInfo getUserBySocketAddress(SocketAddress address)
{
for(int i=1;i<getUserNum();i++)
{
UserInfo user = getUser(i);
if(user.getAddress() != null && user.getAddress().equals(address))
{
return user;
}
}
return nul
}
public int getUserNum()
{
return listModel.size();
}
public UserInfo getUser(int pos)
{
return (UserInfo)listMode.elementAt(pos);
}
class ChangeMusicListener extends MouseAdapter
{
public void mouseClicked(MouseEvent e)
{
if(e.getClickCount() >= 2)
{
UserInfo user = (UserInfo)friendsList.getSelectedValue();
if(user.getChatFrame()== null)
{
user.setChatFrame(new ChatFrame(null,user));
}
if(!user.getChatFrame().isShowing())
{
user.getChatFrame.setVisible(true);
}
}
}
}
public void processMsg(DatagramPacket packet,boolean single)
{
InetSocketAddress srcAddress = (InetSocketAddress)packet.getSocketAddress();
if(single)
{
srcAddress = new InetSocketAddress(srcAddress.getHostName(),srcAddress.getPost()-1);
}
UserInfo srcUser = getUserBySocketAddress(srcAddress);
if(srcUser != null)
{
UserInfo alertUser = single ? srcUser : getUser(0);
if(alertUser.getChatFrame() == null)
{
alertUser.setChatFrame(new ChatFrame(null,alertUser));
}
String tipMsg = single ? "对您说:": "对大家说 :";
alertUser.getChatFrame().addString(srcUser.getName()+tipMsg+"……………… ("+formatter.format(new Date())+")\n"+new String(packet.getData(),0,packet.getLength())+"\n");
if(!alertUser.getChatFrame().isShowing())
{
alertUser.getChatFrame().setVisible(true);
}
}
}
public static void main(String[] args)
{
LanChat lc = new LanChat();
new LoginFrame(lc,"请输入用户名、头像后登录");
}
}
class ImageCellRenderer extends JPanel implements ListCellRenderer
{
private ImageIcon icon;
private String name;
private Color background;
private Color foreground;
public Component getListCellRendererComponent(JList list,Object value,int index,boolean isSelected,boolean cellHasForus)
{
UserInfo user = (UserInfo)value;
icon = new ImageIcon("ico/"+userInfo.getIcon()+".gif");
name = userInfo.getName();
background = isSelected ? list.getSelectionBackground() : list.getBackground();
foreground = isSelected ? list.getSelectionForeground() : list.getForeground();
return this;
}
public void paintComponent(Graphics g)
{
int imageWidth = icon.getImage().getWidth(null);
int imageHeight = icon.getImage().getHeight(null);
g.setColor(background);
g.fillRect(0,0,getWidth(),getHeight());
g.setColor(foreground);
g.drawImage(icon.getImage(),getWidth()/2-imageWidth/2,10,null);
g.setFont(new Font("SansSerif",Font.BOLD,18));
g.drawString(name,getWidth()/2-name.length(0*10,imageHeight+30);
}
public Dimension getPreferredSize()
{
return new Dimension(60,80);
}
}
}