请推荐Java网络编程方面的书,要有类似腾讯QQ这样的及时通信软件开发例子的。(当然用不着QQ那么复杂)

麻烦多推荐,因为不知道在图书馆能不能借到,谢谢了
我之所以说模拟QQ是指只希望服务器端只做中转,而非直接与客户端通信,我是想要实现多个客服端之间的通信

// 在服务器上部署的程序

package wang.socket.Server;
// java 提供的网络功能包
import java.net.*;
// java 提供的输入输出的功能包
import java.io.*;

// 使用线程来处理Socket请求
public class ThreadServer {

public static void main(String[] args) throws Exception {

// 监听服务
ServerSocket server;
// 启动一个监听服务器
server = new ServerSocket(9999);
System.out.println("---------> 一个Socket监听服务器启动:" + server.toString());
while (true) {//循环地响应客户端的请求

//获得客户端连接,也就是要建立一个Socket套接字,由于没有使用线程,多个客户端连接会排队
// ServerSocket的接收套接字的方法是采用队列并等待的方式,如果没有呼入连接,则程序在等待,不向下执行.
Socket client = server.accept();
// 创建线程,让线程去应答客户的请求
new ServerThread(client).start();

}
}
}

// 以线程处理客户的请求
class ServerThread extends Thread {
//主程序的main函数会把创建的Socket作为参数传递给线程执行.

private Socket sk;

public ServerThread(Socket s) {
this.sk = s;
}

@Override
public void run() {
System.out.println("(一个客户请求:)" + this.sk.toString());
// 缓冲区读取器
BufferedReader in;
// 响应器
PrintWriter out;
// 取得客户端的计算机的IP地址
String remoteIP = this.sk.getInetAddress().getHostAddress();
// 取得客户端用于通讯的端口号
int remotePort = this.sk.getLocalPort();
// 在服务器的监控台上显示客户端接入的信息
System.out.println("一个客户端正在连入, IP:" + remoteIP + ", 端口: " + remotePort);

//获得 client 端的输入输出流,为进行交互做准备
try {
in = new BufferedReader(new InputStreamReader(this.sk.getInputStream()));
//获得输出
out = new PrintWriter(this.sk.getOutputStream(), true);

//获得 client 端发送的数据,要注意的是客户端从一个套接字里有可能发送多行的数据。
String content;
// 只有比较明显地给出一个数据流终结的方式才好
while (!(content = in.readLine()).equals("taxend")) {

System.out.println("客户端发来的消息: " + content);
out.println(content);
// 向 client 端发送响应数据
}
//关闭各个流
// out.flush(); 清缓冲区

out.close();
in.close();
// 一次通讯结束,可以关闭socket
this.sk.close();
} catch (Exception ex) {
// ex.printStackTrace();
System.out.println("客户挂断了.........");
}

}
}

// 在客户端部署的程序

package wang.socket.Client;

import java.net.*;
import java.io.*;

/**
*
* @author WangQingda
*/
public class AWTClient extends javax.swing.JFrame {

/** Creates new form AWTClient */
public AWTClient() {

initComponents();
}

/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {

jLabel1 = new javax.swing.JLabel();
jLabel2 = new javax.swing.JLabel();
theServerIP = new javax.swing.JTextField();
jScrollPane1 = new javax.swing.JScrollPane();
theContent = new javax.swing.JTextArea();
jButton1 = new javax.swing.JButton();
jScrollPane2 = new javax.swing.JScrollPane();
theServerOutPut = new javax.swing.JTextArea();

setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setTitle("测试Socket数据流");

jLabel1.setText("请输入服务器地址:");

jLabel2.setText("输入需要提交数据流:");

theServerIP.setText("127.0.0.1");

theContent.setColumns(20);
theContent.setRows(5);
jScrollPane1.setViewportView(theContent);

jButton1.setLabel("提交");
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton1ActionPerformed(evt);
}
});

theServerOutPut.setColumns(20);
theServerOutPut.setRows(5);
jScrollPane2.setViewportView(theServerOutPut);

javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
.addContainerGap()
.addComponent(jScrollPane2))
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
.addGap(31, 31, 31)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel2)
.addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 88, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 317, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addComponent(jLabel1)
.addGap(18, 18, 18)
.addComponent(theServerIP, javax.swing.GroupLayout.PREFERRED_SIZE, 167, javax.swing.GroupLayout.PREFERRED_SIZE)))))
.addContainerGap(31, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(41, 41, 41)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel1)
.addComponent(theServerIP, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addGroup(layout.createSequentialGroup()
.addGap(34, 34, 34)
.addComponent(jLabel2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jButton1))
.addGroup(layout.createSequentialGroup()
.addGap(18, 18, 18)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(13, Short.MAX_VALUE))
);

pack();
}// </editor-fold>

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
try {
//连接 server 端
System.out.println("连接服务器 ...");
Socket client = new Socket(this.theServerIP.getText(), 9999);

//显示已连接
System.out.println("成功接入服务器.");
System.out.println();

//为发送数据做准备
System.out.println("请输入:");
// 注意字符串要以字符流的形式读入。
BufferedReader in = new BufferedReader(new StringReader(this.theContent.getText()));
// 流的输出可以从socket的输出流得到。
PrintWriter out = new PrintWriter(client.getOutputStream(), true);

// 向 server 发送数据
String outTxt;
while ((outTxt = in.readLine()) != null) {
out.println(outTxt);
System.out.println("向服务器发送:"+outTxt);

}
out.flush();
this.theServerOutPut.append("数据已经成功向服务器发送");
//接收来自 server 的响应数据
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
String inTxt;
while ((inTxt = in.readLine()) != null) {
this.theServerOutPut.append(inTxt);

}
// 关闭各个流
in.close();
out.close();
// 客户端退出
client.close();

} catch (Exception e) {
e.printStackTrace();
}
}

/**
* @param args the command line arguments
*/
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {

public void run() {
new AWTClient().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton jButton1;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JTextArea theContent;
private javax.swing.JTextField theServerIP;
private javax.swing.JTextArea theServerOutPut;
// End of variables declaration
}追问

这个程序我基本看了一下,也运行了,除了按了提交按钮后客户端主线程有死循环外,整个程序也没有完成多个客户端之间的P2P通信,在你这个程序中只完成了客户端和服务器之间的通信,我之所以说模拟QQ是指只希望服务器端只做中转,而非直接与客户端通信,所以你的回答我不能采纳,谢谢

温馨提示:内容为网友见解,仅供参考
第1个回答  2011-06-02
可以啊,
你让服务器开个端口,
然后n个客户端连这一个服务器。
客户端发消息的时候通过服务器,在服务器里面做出去。然后发给某个人
代码我现在没有.
不知道我的回答是不是你想要的本回答被网友采纳
相似回答