Java 利用套接字实现两台电脑的通信问题(聊天程序)

你我皆凡人 2015-06-24 09:50:20
我要实现两台电脑,假定在同一局域网下。我写了服务端程序和客户端程序,现在希望类似qq来和别人聊天,分别通过服务器端来转发信息,思路应该怎样,不要涉及数据库的情况下,比如我这里运行客户端程序,对方运行客户端程序。那服务器端源程序在哪里运行呢,可以在我机器上运行么?思路应该怎样啊,新手求具体指导
...全文
1465 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
qq_38408768 2017-07-03
  • 打赏
  • 举报
回复
这个日志文件是咋弄啊,咋分析
qq_33984787 2016-05-05
  • 打赏
  • 举报
回复
楼主好,我是菜鸟,正在做局域网通信软件,而现在一头雾水,求楼主指教。
lemonademix 2015-06-24
  • 打赏
  • 举报
回复
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.tarena.bo.LogData;
import com.tarena.bo.LogRec;
/**
 * DMS客户端
 * @author Administrator
 *
 */
public class DMSClient {
	/*
	 * 第一步,将wtmpx文件日志内容批量解析后
	 * 存入另一个文件中需要的属性。
	 */
	//wtmpx日志文件
	private File logFile;
	
	//保存解析后的日志的文件
	private File textLogFile;
	
	//一次从wtmpx文件中解析日志的条目数
	private int batch;
	
	/*
	 * 记录上次批量读取wtmpx文件后的字节位置
	 * 以便下次读取时从这里继续解析
	 */
	private File lastPositionFile;
	
	/*
	 * 第二步中用到的属性
	 */
	//保存配对日志的文件
	private File logRecFile;
	
	//保存没有配对成功的日志的文件
	private File loginLogFile;
	
	/*
	 * 第三步中用到的属性
	 */
	//服务端的地址
	private String serverHost;
	
	//服务端的端口
	private int serverPort;
	
	
	/**
	 * 构造方法,用于初始化客户端的属性
	 * @throws Exception 
	 */
	public DMSClient() throws Exception{
		try{
			//1:解析config.xml文件,获取配置项
			Map<String,String> config
							= loadConfig();
			
			//打桩
			System.out.println(config);		
			
			//2:根据配置项来初始化对应属性
			init(config);
			
		}catch(Exception e){
			throw e;
		}		
	}
	/**
	 * 根据配置信息初始化客户端属性
	 * @param config
	 * @throws Exception 
	 */
	private void init(Map<String,String> config)
							throws Exception{
		try {
			logFile 
				= new File(
					config.get("logfile")
				);
			
			textLogFile
				= new File(
					config.get("textlogfile")
				);
			
			lastPositionFile
				= new File(
					config.get("lastpositionfile")
				);
			
			batch = Integer.parseInt(
					  config.get("batch")
					);
			
			logRecFile = new File(
					  config.get("logrecfile")
					);
			
			loginLogFile = new File(
					  config.get("loginlogfile")
					);
			
			serverHost = config.get("serverhost");
			
			serverPort = Integer.parseInt(
					  config.get("serverport")
					);
			
			
		} catch (Exception e) {
			throw e;
		}
	}






import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * DMS服务端
 * @author Administrator
 *
 */
public class DMSServer {
	private ServerSocket server;
	
	private ExecutorService threadPool;
	/*
	 * Server端保存所有客户端发送过来的日志
	 * 的文件
	 */
	private File serverLogFile;
	
	/*
	 * 消息队列,用于保存所有客户端发送过来的
	 * 配对日志
	 */
	private BlockingQueue<String> messageQueue;
	
	/**
	 * 构造方法用于初始化服务端
	 * @throws Exception
	 */
	public DMSServer() throws Exception{
		try {
			server = new ServerSocket(8088);
			threadPool = Executors.newFixedThreadPool(30);
			serverLogFile = new File("server_logs.txt");
			messageQueue = new LinkedBlockingQueue<String>();
		} catch (Exception e) {
			throw e;
		}
	}
	/**
	 * 服务端开始工作的方法
	 */
	public void start(){
		try {
			/*
			 * 启动用于保存客户端发送过来的配对
			 * 日志的线程
			 */
			SaveLogHandler saveHandler
				= new SaveLogHandler();
			Thread t = new Thread(saveHandler);
			t.start();
			
			while(true){
				Socket socket
					= server.accept();
				//启动一个线程,来完成交互
				ClientHandler clientHandler
					= new ClientHandler(socket);
				//将任务交给线程池分配线程启动
				threadPool.execute(clientHandler);
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args){
		DMSServer server;
		try {
			server = new DMSServer();
			server.start();
		} catch (Exception e) {
			System.out.println("服务端启动失败!");
			e.printStackTrace();
		}
		
	}
	/**
	 * 该线程用来处理给定的客户端的消息
	 * 主要作用:
	 * 	读取客户端发送过来的每一条配对日志
	 *  并保存至文件中
	 * @author Administrator
	 *
	 */
	class ClientHandler implements Runnable{
		//当前线程要处理的客户端的Socket
		private Socket socket;
		public ClientHandler(Socket socket){
			this.socket = socket;
		}
		
		public void run(){
			PrintWriter pw = null;
			try {
				pw = new PrintWriter(
					new OutputStreamWriter(
						socket.getOutputStream(),
						"UTF-8"
					)
				);
				/*
				 * 通过开客户端的Socket获取
				 * 输入流,循环按行读取每一条
				 * 客户端发送过来的配对日志,
				 * 然后将其写入本地文件中。
				 * 当保存后,回复客户端“OK”
				 * 若出现异常,回复客户端"ERROR"
				 */
				BufferedReader br
					= new BufferedReader(
						new InputStreamReader(
							socket.getInputStream()
							,
							"UTF-8"
						)
					);
				
				/*
				 * 循环读取客户端发送过来的每一个字符串
				 */
				String log = null;
				while((log = br.readLine())!=null){
//					System.out.println(log);
					if("OVER".equals(log)){
						break;
					}
					//将该字符串存入消息队列
					messageQueue.offer(log);		
				}
				
				//响应客户端操作成功!
				pw.println("OK");
				pw.flush();
			} catch (Exception e) {
				//响应客户端操作失败!
				pw.println("ERROR");
				pw.flush();
			} finally{
				/*
				 * 当客户端与服务端断开后,同样
				 * 这里也和客户端断开,释放资源
				 */
				if(socket != null){
					try {
						socket.close();
					} catch (IOException e) {
					}
				}
			}
		}
	}
	
	/**
	 * 该线程的作用是循环从消息队列中
	 * 取出每一条日志,然后将其写入本地
	 * 文件保存
	 * @author Administrator
	 *
	 */
	class SaveLogHandler implements Runnable{
		public void run(){
			PrintWriter pw = null;
			try {
				pw = new PrintWriter(serverLogFile);
				
				/*
				 * 循环从队列中取出每一条日志,写入
				 * 文件,若队列中没有日志了,就等待
				 * 一会。
				 */
				while(true){
					if(messageQueue.size()>0){
						String log = messageQueue.poll();
						pw.println(log);
					}else{
						//先将缓存中的全部写入文件
						pw.flush();
						//休息半秒钟
						Thread.sleep(500);
					}
				}
				
				
			} catch (Exception e) {
				e.printStackTrace();
			} finally{
				if(pw != null){
					pw.close();
				}
			}
		}
	}
	
}







import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import com.tarena.bo.LogData;

/**
 * 该类用于处理客户端相关的IO操作。
 * 该类是一个工具类,所以定义的方法都是静态的。
 * @author Administrator
 *
 */
public class IOUtil {
	/**
	 * 该方法用于从给定的文件中读取第一行字符串
	 * 并将其转换为long值返回。若读取过程中出现
	 * 异常,会将其抛出给调用者。
	 * @param file
	 * @return
	 * @throws Exception 
	 */
	public static long readLong(File file)
							throws Exception{
		BufferedReader br = null;
		try {
			br = new BufferedReader(
					new InputStreamReader(
						new FileInputStream(
						  file		
						)
					)
			     );
			
			String line = br.readLine().trim();
			
			return Long.parseLong(line);
			
		} catch (Exception e) {
			throw e;
		} finally{
			if(br != null){
				br.close();
			}
		}
	}
	
	/**
	 * 从给定的RandomAccessFile当前位置开始
	 * 连续读取给定长度的字节量,并将其转换为
	 * 字符串返回
	 * @param raf
	 * @param length
	 * @return
	 * @throws Exception 
	 */
	public static String readString(
		RandomAccessFile raf,int length)
							throws Exception{
		try {
			byte[] buf = new byte[length];
			raf.read(buf);
			return new String(buf,"iso8859-1");
		} catch (Exception e) {
			throw e;
		}
	}
	
	/**
	 * 将给定的集合中的每一个元素的toString返回的
	 * 字符串以行为单位写入给定的文件中
	 * @param file
	 * @param c
	 * @throws Exception 
	 */
	public static void saveCollection(
						File file,Collection c)
							  throws Exception{
		PrintWriter pw = null;
		try {
			pw = new PrintWriter(file);
			for(Object o : c){
				pw.println(o.toString());
			}
			
		} catch (Exception e) {
			throw e;
		} finally{
			if(pw != null){
				pw.close();
			}
		}
	}
	/**
	 * 将给定的long值以行为单位用字符串的形式
	 * 写入给定文件中
	 * @param file
	 * @param l
	 * @throws Exception 
	 */
	public static void saveLong(
						File file,long l) 
						throws Exception{
		PrintWriter pw = null;
		try {
			pw = new PrintWriter(file);
			pw.println(l);//不是"1"!
		} catch (Exception e) {
			throw e;
		} finally{
			if(pw != null){
				pw.close();
			}
		}
	}
	
	/**
	 * 该方法用于从给定的文件中读取每一行字符串
	 * 然后将其转换为若干个LogData实例并存入
	 * 集合后返回该集合
	 * @param file
	 * @return
	 * @throws Exception 
	 */
	public static List<LogData> 
						readLogData(File file)
						throws Exception{
		BufferedReader br = null;
		try {
			br = new BufferedReader(
					new InputStreamReader(
						new FileInputStream(
							file	
						)	
					)
				 );
			List<LogData> list
				= new ArrayList<LogData>();
			String line = null;
			while((line=br.readLine())!=null){
				LogData log = new LogData(line);
				list.add(log);
			}
			return list;
		} catch (Exception e) {
			throw e;
		} finally{
			if(br != null){
				try{
					br.close();
				}catch(Exception e){				
				}
			}
		}
		
	}
	/**
	 * 将给定文件中的每一行字符串(配对日志)
	 * 读取出来并存入集合,然后将该集合返回
	 * @param file
	 * @return
	 * @throws Exception 
	 */
	public static List<String> 
					readLogRec(File file)
					throws Exception{
		BufferedReader br = null;
		try {
			br = new BufferedReader(
					new InputStreamReader(
						new FileInputStream(
							file
						)
					)
				 );
			List<String> list
				= new ArrayList<String>();
			String line = null;
			while((line = br.readLine())!=null){
				list.add(line);
			}
			return list;
			
		} catch (Exception e) {
			throw e;
		} finally{
			if(br != null){
				try {
					br.close();
				} catch (IOException e) {
				}
			}
		}
		
	}
	
}

三个类~  具体思路我忘了。 你自己看吧
	
lemonademix 2015-06-24
  • 打赏
  • 举报
回复
私信我,我可以给类似的代码
qq_20480255 2015-06-24
  • 打赏
  • 举报
回复
服务器随便在哪一台电脑上都可以的,只要在那个局域网内。 先启动服务器,再在不同电脑上启动客户端。都可以通信了
你我皆凡人 2015-06-24
  • 打赏
  • 举报
回复
引用 11 楼 u012606207 的回复:
恩 谢谢各位,已成功实现同一局域网下链接两台电脑,方法是:对方既作为服务器也同时启动一个服务器,而我只做客户端,互相能收到对方发的信息。很开心。不过意外的是:我的电脑作为服务器时对方连接我的会超时,不知道原因。不过大致没问题了,谢谢各位!
打错字: 是同时启动一个客户端
你我皆凡人 2015-06-24
  • 打赏
  • 举报
回复
恩 谢谢各位,已成功实现同一局域网下链接两台电脑,方法是:对方既作为服务器也同时启动一个服务器,而我只做客户端,互相能收到对方发的信息。很开心。不过意外的是:我的电脑作为服务器时对方连接我的会超时,不知道原因。不过大致没问题了,谢谢各位!
你我皆凡人 2015-06-24
  • 打赏
  • 举报
回复
引用 9 楼 alan19931103 的回复:
[quote=引用 6 楼 u012606207 的回复:] [quote=引用 5 楼 alan19931103 的回复:] 两台电脑和一台电脑没区别,把地址弄好就可以了
也就是说只要对方有eclipse 能运行客户端代码,我作为服务器端,然后我本地再运行客户端代码,然后IP地址都填服务器端IP地址也就是本机就行了对么?[/quote] 另一台电脑的服务器地址不是本机啊,是运行服务器的那台的地址[/quote] 理解,谢谢,我成功了
alan19931103 2015-06-24
  • 打赏
  • 举报
回复
引用 6 楼 u012606207 的回复:
[quote=引用 5 楼 alan19931103 的回复:] 两台电脑和一台电脑没区别,把地址弄好就可以了
也就是说只要对方有eclipse 能运行客户端代码,我作为服务器端,然后我本地再运行客户端代码,然后IP地址都填服务器端IP地址也就是本机就行了对么?[/quote] 另一台电脑的服务器地址不是本机啊,是运行服务器的那台的地址
tony4geek 2015-06-24
  • 打赏
  • 举报
回复
同样个局域网,一个接受,一个发送。 不同的电脑不同的ip 。 就好比一个局域网,一台电脑可以访问另一台电脑一样的。
你我皆凡人 2015-06-24
  • 打赏
  • 举报
回复
引用 1 楼 qq_20480255 的回复:
服务器随便在哪一台电脑上都可以的,只要在那个局域网内。 先启动服务器,再在不同电脑上启动客户端。都可以通信了
也就是说只要对方有eclipse 能运行客户端代码,我作为服务器端,然后我本地再运行客户端代码,然后IP地址都填服务器端IP地址也就是本机,这样就行了对么?
你我皆凡人 2015-06-24
  • 打赏
  • 举报
回复
引用 5 楼 alan19931103 的回复:
两台电脑和一台电脑没区别,把地址弄好就可以了
也就是说只要对方有eclipse 能运行客户端代码,我作为服务器端,然后我本地再运行客户端代码,然后IP地址都填服务器端IP地址也就是本机,这样就行了对么?
alan19931103 2015-06-24
  • 打赏
  • 举报
回复
两台电脑和一台电脑没区别,把地址弄好就可以了
你我皆凡人 2015-06-24
  • 打赏
  • 举报
回复
谢谢,其实我代码写的差不多了,只不过现在想实现两台电脑而不是只在我的电脑上。谢谢你的代码和你们的思路。

62,615

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧