好久没有写javaeye博客了,最近写了个TCP Socket编程,和大家一起分享!
聊天原理:启动TCP服务端,等待客户端连接,当客户端连接到服务端后,服务端创建一个线程针对该客户端进行读写,服务端继续在指定端口监听客户端连接。客户端连接成功后,创建写线程和读线程,来与服务器端进行通信。服务器端线程接收到客户端的信息,再把该信息转发给消息的目的地客户端。目的地客户端通过发送线程发送消息给服务器端,服务器端接收到消息,再把消息转发给目的地客户端。服务器端线程并不会主动地发送消息给客户端,服务器端线程只是在中转客户端发送过来的信息,把消息发送给指定的目的地客户端而已。
如何实现从客户端A发送消息给客户端B呢?
1、客户端A通过写线程,写入消息到服务器端
2、服务器端接收到客户端A的消息,并解析消息内容,得知消息是要发送给客户端B,服务器端线程写入消息给客户端B
3、客户端B读取线程读取到服务器线程发送来的数据
这样的就完成了从客户端A发送消息到客户端B,通过客户端B也通过同样的方式发送消息给客户端A。完成双向通信。
服务端:
package com.guchao.chat;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class TCPServer {
private Map<String, Socket> sockets = new HashMap<String, Socket>();
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
new TCPServer().go();
}
public void go(){
ServerSocket ss = null;
try {
ss = new ServerSocket(8888);
System.out.println("服务器启动成功,在8888端口监听用户连接!");
} catch (IOException e1) {
e1.printStackTrace();
}
Socket s = null;
int i = 0;
while(true){
try {
s = ss.accept();
String clientName = "Client_"+(++i);
sockets.put(clientName, s);
sendMessageToOtherClients(clientName);
System.out.println(clientName+"连接到服务器!");
} catch (IOException e) {
e.printStackTrace();
}
ReadAndWriteThread t = new ReadAndWriteThread(s);
new Thread(t).start();
}
}
private void sendMessageToOtherClients(String clientName) {
if(sockets != null && sockets.size() > 0){
for (Iterator<String> iterator = sockets.keySet().iterator(); iterator.hasNext();) {
String key = (String) iterator.next();
Socket s = sockets.get(key);
try {
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
dos.writeUTF(clientName+"已经登陆了服务器!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class ReadAndWriteThread implements Runnable{
private DataInputStream dis = null;
public ReadAndWriteThread(Socket s){
try {
dis = new DataInputStream(s.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
String str = "";
while(true){
try {
/**
* 定义消息格式为hello,jjkdfjaf*客户端名称*
* 例如:hello,zhangsan*Client_2*
* 表示消息hello,zhangsan发送给Client_2
*/
str = dis.readUTF();
if("bye".equals(str))
break;
sendMessageToClient(str);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private void sendMessageToClient(String str){
int startPosition = str.lastIndexOf("*", str.lastIndexOf("*")-1);
int endPosition = str.lastIndexOf("*");
if(startPosition > 0 && endPosition > 0 && endPosition > startPosition){
String clientName = str.substring(startPosition+1, endPosition);
Socket s = sockets.get(clientName);
DataOutputStream dos = null;
try {
if(s != null){
dos = new DataOutputStream(s.getOutputStream());
dos.writeUTF(str);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
客户端:
package com.guchao.chat;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;
public class TCPClient {
public static void main(String[] args) throws UnknownHostException, IOException{
new TCPClient().go();
}
public void go() {
try {
Socket s = new Socket("127.0.0.1",8888);
// 启动读线程,从socket中读取信息
RecvThread recv = new RecvThread(s);
new Thread(recv).start();
// 启动写线程,写入信息到socket中
SendThread send = new SendThread(s);
new Thread(send).start();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
class RecvThread implements Runnable{
private DataInputStream dis = null;
public RecvThread(Socket s){
try {
dis = new DataInputStream(s.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
String str = "";
while(true){
try {
//从socket中读取信息
str = dis.readUTF();
if("bye".equals(str))
break;
System.out.println("received message:"+str);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class SendThread implements Runnable{
private DataOutputStream dos;
public SendThread(Socket s){
try {
dos = new DataOutputStream(s.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
String str = "";
while(true){
System.out.println("input message:");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try {
str = br.readLine();
// 写入信息到socket中
dos.writeUTF(str);
if("bye".equals(str))
break;
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}