您的位置:首页 > 理论基础 > 计算机网络

Java网络----Socket, 多线程实现内网多人聊天及一对一聊天

2017-08-22 13:25 896 查看
本文属于网络编程,才用Socket+多线程编程,实现使用控制台进行多人互动聊天,以及一对一互动聊天,

服务器端代码:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URLDecoder;
import java.util.ArrayList;

public class SimpleServer {

//用于保存当前连接的用户
public static ArrayList<Socket> socketList=new ArrayList<Socket>();

/**
* 服务器主函数
* @param args
* @throws Exception
*/
public static void main(String[] args)throws Exception {
//创建一个serverSocket,用于监听客户端Socket的连接请求
ServerSocket serverSocket = new ServerSocket(10002);//10002为此服务器的端口号
System.out.println("服务启动.....");
//采用循环不断接收来自客户端的请求
while (true) {
//每当接收到客户端的请求时,服务器端也对应产生一个Socket
Socket socket = serverSocket.accept();
System.out.println("服务连接....");
// 把连接的客户端加入到list列表中
socketList.add(socket);
System.out.println("当前有:"+socketList.size()+"个客户端连接");
//启动一个新的线程
//任务线程,每个连接用都有一个属于自己专用的任务线程

4000
//这个线程内会处理信息的发送和响应
new MyThread(socket,socketList).start();
}
}
}
class MyThread extends Thread {

//一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。建立网络通信连接至少要一对端口号(socket)
Socket client;

ArrayList<Socket> clients;

BufferedReader br;

public MyThread(Socket client,ArrayList<Socket> clients)throws Exception {
super();
this.client = client;
this.clients = clients;

br = new BufferedReader(new InputStreamReader(this.client.getInputStream()));
}

//把接收到的消息发送给各客户端
public void run() {
try {
String content=null;
while(true){
//从某个客户端读取信息
if((content=br.readLine())!=null) {
for(Socket socket:clients){
if(client!=socket){
//把读取到的消息发送给各个客户端
PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
pw.println(content);
}
}
content = URLDecoder.decode(content, "UTF-8");
System.out.println(content);

}
}
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}


客户端代码:

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.URLDecoder;

public class Client {
/**
* @param args
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
//创建连接到本机,端口为10002的socket
System.out.println("123");
Socket client = new Socket("192.168.1.49", 10002);

new MyThread(client).start();
InputStream is = client.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));

while (true) {
String msg = br.readLine();
//对收到的信息进行解码
msg=URLDecoder.decode(msg, "UTF-8");
System.out.println(msg);
}
}

}


客户端线程方法:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.URLEncoder;
import java.net.UnknownHostException;

public class MyThread extends Thread {
Socket client;
//消息发送人名称,即本机的名称
String hostName = "";
public MyThread(Socket client) {
super();
this.client = client;
try {
InetAddress addr = InetAddress.getLocalHost();
hostName =addr.getHostName().toString(); //获取本机计算机名称
} catch (UnknownHostException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
public void run() {
// 发出消息
try {
BufferedReader br = new BufferedReader(new InputStreamReader(
System.in));
PrintWriter pw = new PrintWriter(client.getOutputStream(), true);
// 把输入的内容输出到socket
while (true) {
String msg = br.readLine();
//对发出的消息进行编码
msg = URLEncoder.encode(hostName + "说:"+ msg, "UTF-8");
pw.println(msg);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}


至此简单的多人聊天已经实现

运行服务器,再运行两台客户机,进行消息发送,通过服务器发送其他客户机,

效果如下:

服务器打印内容:

服务启动…..

服务连接….

当前有:1个客户端连接

服务连接….

当前有:2个客户端连接

Vip_HYP-PC说:我是客户A

Vip_HYP-PC说:我是客户B

客户机B打印内容:

Vip_HYP-PC说:我是客户A

我是客户B

当然这样的效果过于简陋,,比如我们可以让客户机来查看有几个用户?以及对某个特定的用户进行消息发送?想到这些,那就在服务器端先加上业务逻辑把.

先进行客户端改变:

删除hostName 定义实现,改为电脑ip标识:

//消息发送人名称
String userName = "";
//消息发送人IP地址,身份的唯一标识
String hostIP="";


MyThread方法修改

public MyThread(Socket client) {
super();
this.client = client;
try {
InetAddress addr = InetAddress.getLocalHost();
hostIP=addr.getHostAddress().toString();//获取本机的计算机IP
} catch (UnknownHostException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}


run方法增加username判断

String msg = br.readLine();
//刚登录,进行用户名填写
if(userName.equals("")){
//对发出的消息进行编码
msg = URLEncoder.encode(hostIP+"__"+ msg, "UTF-8");//添加用户IP做唯一标识
pw.println(msg);
}else{
//添加用户IP做唯一标识
msg = URLEncoder.encode(hostIP+"__"+userName + "__说:"+ msg, "UTF-8");
pw.println(msg);
}


接下来是服务器端代码修改:

首先mian方法中,对每次连接用户发送一个消息,进行用户名注册

PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
pw.println("请输入您的用户名,进行聊天");
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//创建用户名
String content = "";
if((content=br.readLine())!=null) {
//以__拆分消息内容,ip,username
content = URLDecoder.decode(content, "UTF-8");
String[] contents = content.split("__");
userNameMap.put(contents[0], contents[1]);
}


重点到了,对获取到的消息进行判断执行:

if((content=br.readLine())!=null) {
content = URLDecoder.decode(content, "UTF-8");
//以__拆分消息内容,ip,username+内容
String[] contents = content.split("__");
if(contents.length==3){
if(contents[2].equals("说:1")){//查看所有登录用户
for(Socket socket:clients){
if(client!=socket){//不是自身
PrintWriter pw = new PrintWriter(client.getOutputStream(), true);
pw.println("用户名:"+userNameMap.get(socket.getInetAddress().toString())+",ip地址:"+socket.getInetAddress());
}
}
}
}
if(contents[2].equals("说:2")){//进行指定人聊天
//进行消息指定发送
}
if(contents[2].equals("说:e")){//退出指定人聊天
//销毁两用户的一对一关联,未实现
}else{
for(Socket socket:clients){
if(client!=socket){
//把读取到的消息发送给各个客户端
PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
pw.println(contents[1]+'['+contents[0]+']'+contents[2]);
}
}
}
}
}


贴出效果图:



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐