java applet 聊天_java 聊天程序

package cn.apr.chart;

import java.net.*;

import java.io.*;

import java.util.*;

public class ChatServer {

/**

* @param args

*            m_threads是一个Vector静态变量,维护所有Server方的ServerThread对象,

*            通过该变量能向所有加入聊天室的聊天者ChatApplet广播信息,撤销退出的聊天者。

*            聊天服务者ChatServer的主方法。该方法监听聊天者Chat Applet的请求, 并为新连接的聊天者创建一个服务线程。

*/

public static void main(String[] args) {

// TODO Auto-generated method stub

ServerSocket socket = null;

Vector m_threads = new Vector();

System.out.println("listen...");

try {

// 设置ServerSocket监听端口号为5555,这个数字必须和程序聊天者ChatApplet中的port参数一致

socket = new ServerSocket(5555);

} catch (Exception e) {

System.out.println("new ServerSocket() failed!");

return;

}

try {

int nid = 0;

while (true) {

// 监听是否有新聊天者Chat Applet连接到聊天Server,

// 线程运行到该语句会封锁,直到有新的连接产生

Socket s = socket.accept();

System.out.println("accepted");

// 创建一个新的ServerThread

ServerThread st = new ServerThread(s, m_threads);

// 为该线程设置一个ID号

st.setID(nid++);

// 将线程加入到m_threads Vector中

m_threads.addElement(st);

// 启动服务线程

new Thread(st).start();

// 通知所有ChatApplet有一个新的网友加入

for (int i = 0; i < m_threads.size(); i++) {

ServerThread st1 = (ServerThread) m_threads.elementAt(i);

st1.write("welcome" + st.getID() + "to enter chatroom!");

}

System.out.println("Listen again...");

}

} catch (Exception e) {

System.out.println("Server is down...");

}

}

}

// 监听线程,监听对应的Chat Applet是否有信息传来

class ServerThread implements Runnable {

Vector m_threads;

Socket m_socket = null;

DataInputStream m_in = null;

DataOutputStream m_out = null;

int m_nid;

// 初始化线程

public ServerThread(Socket s, Vector threads) {

m_socket = s;

m_threads = threads;

try {

// 构造数据输入、输出流对象

m_in = new DataInputStream(m_socket.getInputStream());

m_out = new DataOutputStream(m_socket.getOutputStream());

} catch (Exception e) {

}

}

public void run() // 线程的执行体

{

System.out.println("thread is running");

try {

while (true) {

// 监听对应的ChatApplet是否传来消息

// 线程封锁在m_in.readUTF()中,直到有信息传来才返回

String s = m_in.readUTF();

if (s == null)

break;

// 如果Chat Applet传来的信息为“leave”,则通知所有其他的ChatApplet自己推出了

if (s.trim().equals("leave"))

for (int i = 0; i < m_threads.size(); i++) {

ServerThread st = (ServerThread) m_threads.elementAt(i);

st.write("***" + getID() + "leave..." + "***");

}

else

// 向所有ChatApplet广播该消息

for (int i = 0; i < m_threads.size(); i++) {

ServerThread st = (ServerThread) m_threads.elementAt(i);

st.write("" + s);

}

} // while(true)

} catch (Exception e) {

e.printStackTrace();

}

// 从m_threads Vector中删除该线程,表示该线程已经离开聊天室

m_threads.removeElement(this);

System.out.println("remove element!");

try {

m_socket.close();

} catch (Exception e) {

}

}

// 将msg送回对应的Applet

public void write(String msg) {

synchronized (msg) {

try {

m_out.writeUTF(msg);

} catch (IOException e) {

}

}

}

public int getID() // 获得该线程的ID

{

return m_nid;

}

public void setID(int nid) // 设置线程的ID

{

m_nid = nid;

}

}

//

package cn.apr.chart;

import java.awt.*;

import java.applet.*;

import java.io.*;

import java.net.*;

//继承Applet,实现Runnable

public class ChatApplet1 extends Applet implements Runnable {

TextArea m_textarea; // 接受消息显示窗口

TextField m_textfield; // 发送消息输入窗口

DataInputStream m_in; // 消息输入流

DataOutputStream m_out; // 消息输出流

/**

* @param args

*  ChatApplet的初始化方法

*/

public void init() {

// 创建窗口

setLayout(null);

setSize(426, 266);

m_textarea = new TextArea(10, 10);

m_textfield = new TextField();

m_in = null;

m_out = null;

// 初始化Appleton,并连接到聊天服务者

try {

// 获取applet的URL,即通过服务器地址

URL url = getCodeBase();

// 获取服务器IP地址

InetAddress inetaddr = InetAddress.getByName(url.getHost());

Socket m_socket;

// 屏幕显示服务器IP地址、通信协议

System.out.println("Server:" + inetaddr + "" + url.getHost() + ""

+ url.getProtocol());

// 创建与服务器IP地址连接的套接口,5555是聊天服务器套接口端口

m_socket = new Socket(inetaddr, 5555);

// 在套接口上建立输入流

m_in = new DataInputStream(m_socket.getInputStream());

// 在套接口上建立输出流

m_out = new DataOutputStream(m_socket.getOutputStream());

} catch (Exception e) {

System.out.println("Error:" + e);

}

setLayout(new BorderLayout());

add("Center", m_textarea);

add("South", m_textfield);

m_textarea.setEditable(false);

// 启动监听线程

new Thread(this).start();

}

// 当聊天者在消息输入窗口键入回车后,读取字符串,发送给聊天服务者。

public boolean handleEvent(Event event) {

String b = m_textfield.getText();

if ((event.target == m_textfield) && (event.id == Event.ACTION_EVENT)) {

m_textfield.setText("");

// 将聊天者输入的消息发送给ChatServer

try {

m_out.writeUTF(b); // 向聊天服务者发送一个UFT格式字符串

} catch (IOException e) {

}

return true;

} else

return super.handleEvent(event);

}

// 聊天者监听对应的服务线程,在读取对应服务线程传来的消息,并显示在通信显示窗口中

public void run() {

try {

while (true) {

// 聊天者监听对应服务线程发来的消息,它将封锁在该语句中,直到消息到来

String s = m_in.readUTF(); // 读一个UTF格式字符串

if (s != null)

// 将消息显示在信息显示窗口中

m_textarea.append(s + "\n");

}

} catch (Exception e) {

m_textarea.append("Network problem or Server down.\n");

m_textfield.setVisible(false);

}

}

public void stop() {

try {

m_out.writeUTF("leave");

} catch (IOException e) {

}

}

public static void main(String[] args) {

// TODO 自动生成方法存根

}

}

packagecn.apr.socket;importorg.eclipse.swt.SWT;importorg.eclipse.swt.layout.FillLayout;importorg.eclipse.swt.layout.FormAttachment;importorg.eclipse.swt.layout.FormData;importorg.eclipse.swt.layout.FormLayout;importorg.eclipse.swt.layout.GridData;importorg.eclipse.swt.layout.GridLayout;importorg.eclipse.swt.widgets.Button;importorg.eclipse.swt.widgets.Composite;importorg.eclipse.swt.widgets.Display;importorg.eclipse.swt.widgets.Label;importorg.eclipse.swt.widgets.Shell;importorg.eclipse.swt.widgets.Text;public classMyClient {protectedShell shell;privateText textChatInfo;privateText textMsg;/*** Launch the application.

*

*@paramargs*/

public static voidmain(String[] args) {try{

MyClient window= newMyClient();

window.open();

}catch(Exception e) {

e.printStackTrace();

}

}/*** Open the window.*/

public voidopen() {

Display display=Display.getDefault();

createContents();

shell.open();

shell.layout();while (!shell.isDisposed()) {if (!display.readAndDispatch()) {

display.sleep();

}

}

}/*** Create contents of the window.*/

protected voidcreateContents() {

shell= newShell();

shell.setSize(450, 300);

shell.setText("SWT Application");

GridLayout layout= new GridLayout(3, false);

shell.setLayout(layout);/*line begin*/Label lblServerIp= newLabel(shell, SWT.NONE);

lblServerIp.setAlignment(SWT.RIGHT);

lblServerIp.setText("IP:");

Text textServerIP= newText(shell, SWT.BORDER);

GridData gd= newGridData();

gd.horizontalAlignment=GridData.FILL;

gd.grabExcessHorizontalSpace= true;

gd.horizontalSpan= 2;

gd.widthHint= 200;

textServerIP.setLayoutData(gd);

textServerIP.setText("127.0.0.1");/*line begin*/Label lblPort= newLabel(shell, SWT.NONE);

lblPort.setAlignment(SWT.RIGHT);

lblPort.setText("Port:");

Text textServerPort= newText(shell, SWT.BORDER);

gd= newGridData();

gd.horizontalAlignment=GridData.FILL;

gd.grabExcessHorizontalSpace= true;

gd.horizontalSpan= 2;

textServerPort.setLayoutData(gd);

textServerPort.setText("6666");/*line begin*/

newLabel(shell, SWT.NONE);

Text textChatInfo= new Text(shell, SWT.BORDER|SWT.MULTI);

gd= newGridData();

gd.horizontalAlignment=GridData.FILL;

gd.verticalAlignment=GridData.FILL;

gd.grabExcessHorizontalSpace= true;

gd.grabExcessVerticalSpace= true;

gd.horizontalSpan= 2;

gd.heightHint= 150;

textChatInfo.setLayoutData(gd);/*line begin*/

newLabel(shell, SWT.NONE);

Text textMsg= newText(shell, SWT.BORDER );

gd= newGridData();

gd.horizontalAlignment=GridData.FILL;

gd.horizontalSpan= 1;

gd.grabExcessHorizontalSpace= true;

textMsg.setLayoutData(gd);

Button btnSend= newButton(shell, SWT.NONE);

btnSend.setText("Send");

gd= newGridData();

gd.grabExcessHorizontalSpace= true;

btnSend.setLayoutData(gd);

}

}

先运行safechat包里的greetigserver.class,之后运行greetingclient.class即可。 如遇报错,请参考:https://blog.csdn.net/fengzun_yi/article/details/104497160 实现过程: 1. 采用TCP通信协议完成接收者发送者双方的消息传递。 2. 利用Diffie-Hellman密钥交换协议生成对称加密通信的通信密钥。 3. 为防止中间人攻击,采用RSA非对称加密算法协助DH算法完成密钥交换。具体过程如下: a. 接收者与发送者双方各自利用RSA算法生成自己的公私钥,并生成数字证书,并在一个CA进行认证。 b. 在DH密钥交换阶段,A生成A的DH协商密钥用于发送给B,该密钥与接收方私钥生成最终通信密钥。发送DH密钥时,A先用自己的私钥加密DH协商密钥,再去CA获得一个真实的B的公钥,用B的公钥对加密过的协商密钥再做一次加密,发送给B。(因为是用B的公钥加密过,只有B有B的私钥,所以接收信息只有B自己可以解密查看,又因为是用A的私钥加密过的,只有A有A的私钥,所以只有用A的公钥可以进行解密,所以可以保证协商密钥确实是A发送过来的,而且发送的信息也无法被中间人解密。)B收到信息之后,先用自己的私钥解密,然后去CA获得A的公钥再对消息解密一次,获得A的DH密钥。B发给A的过程同上。 c. 之后双方执行DH生成本地密钥的过程。A利用B发送过来的密钥和A的DH私钥生成通信密钥。B利用A发送过来的密钥和B的DH私钥生成通信密钥。根据DH原理,两者生成的通信密钥是相同的。 4. 利用上一步生成的通信密钥,采用AES对称加密算法进行加密通信。 为了方便起见,并没用对A和B双方进行颁发证书的操作,A的公钥默认B已经从CA获得,B的公钥默认A已经从CA获得。并且采用java控制台交互,仅仅为演示原理及简单效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值