Client/Server Chat Program


/ Published in: Java
Save to your folder(s)



Copy this code and paste it in your HTML
  1. In a nutshell, I just recently starting attempting to use Sockets and decided I wanted to give a go at a chat program. I have some experience with threads and based on the weird deadlock issues I have come to the conclusion that I must have some non thread-safe calls somewhere. Any help would be appreciated.
  2.  
  3. *Client-Side Files*
  4. {code}
  5. public class Client extends Thread
  6. {
  7. private Socket conn;
  8. private ObjectOutputStream out;
  9. private ObjectInputStream in;
  10.  
  11. public Client()
  12. {
  13. conn = null;
  14. out = null;
  15. in = null;
  16. }
  17.  
  18. public Client(String ip)
  19. {
  20. obsList = new ArrayList<IClientObs>();
  21.  
  22. try
  23. {
  24. conn = new Socket(ip, 5000);
  25. if (conn.isConnected())
  26. {
  27. out = new ObjectOutputStream(conn.getOutputStream());
  28. in = new ObjectInputStream(conn.getInputStream());
  29. }
  30. notify("Server: Welcome! Connected to '" + conn.getRemoteSocketAddress() + "'.\n");
  31. }
  32. catch(IOException e)
  33. {
  34. notify("Console: Error while attempting to connect to the server.\n");
  35. System.err.println("ConnClient:: ConnClient() -> " + e.getMessage() + "\n");
  36. }
  37. }
  38.  
  39. public Client(Socket pConn)
  40. {
  41. obsList = new ArrayList<IClientObs>();
  42.  
  43. try
  44. {
  45. conn = pConn;
  46. if (conn.isConnected())
  47. {
  48. out = new ObjectOutputStream(conn.getOutputStream());
  49. in = new ObjectInputStream(conn.getInputStream());
  50. }
  51. notify("Server: Welcome! Connected to '" + conn.getRemoteSocketAddress() + "'.\n");
  52. }
  53. catch(IOException e)
  54. {
  55. notify("Console: Error while attempting to connect to the server.\n");
  56. System.err.println("ConnClient:: ConnClient() -> " + e.getMessage() + "\n");
  57. }
  58. }
  59.  
  60. public void run()
  61. {
  62. while (conn.isConnected())
  63. {
  64. nextMsg();
  65. }
  66. }
  67.  
  68. public String nextMsg()
  69. {
  70. String msg = "";
  71. try
  72. {
  73. msg = (String)in.readObject();
  74. notify(msg);
  75. }
  76. catch(IOException e)
  77. {
  78. System.err.println("ConnClient:: nextMsg() -> " + e.getMessage() + "\n");
  79. }
  80. {
  81. System.err.println("ConnClient:: nextMsg() -> " + e.getMessage() + "\n");
  82. }
  83. finally
  84. {
  85. //notify("Console: Error while attempting to read messages from server.\n");
  86. }
  87. return(msg);
  88. }
  89.  
  90. public boolean sendMsg(String msg)
  91. {
  92. boolean sentMsg = false;
  93. try
  94. {
  95. if (out != null)
  96. {
  97. out.writeObject(msg);
  98. out.flush();
  99. sentMsg = true;
  100. }
  101. }
  102. catch(IOException e)
  103. {
  104. notify("Console: Error while attempting to send message to server.\n");
  105. System.err.println("ConnClient:: sendMsg() -> " + e.getMessage() + "\n");
  106. }
  107. return(sentMsg);
  108. }
  109.  
  110. public void closeConn()
  111. {
  112. try
  113. {
  114. if (conn != null && in != null && out != null)
  115. {
  116. notify("Server: you have been disconnected from '" + conn.getRemoteSocketAddress() + "'.\n");
  117. sendMsg("~~QUIT~~");
  118. conn.close();
  119. in.close();
  120. out.close();
  121. }
  122. }
  123. catch(IOException e)
  124. {
  125. notify("Console: Error while closing connection.");
  126. }
  127. }
  128.  
  129. public String getIP()
  130. {
  131. return(conn.getRemoteSocketAddress().toString());
  132. }
  133.  
  134. public boolean isConnected()
  135. {
  136. return(conn.isConnected());
  137. }
  138.  
  139. private ArrayList<IClientObs> obsList;
  140.  
  141. public void addObserver(IClientObs obs)
  142. {
  143. if (obs != null)
  144. {
  145. obsList.add(obs);
  146. }
  147. }
  148.  
  149. public void delObserver(IClientObs obs)
  150. {
  151. if (obs != null)
  152. {
  153. obsList.remove(obs);
  154. }
  155. }
  156.  
  157. private void notify(String msg)
  158. {
  159. for(IClientObs obs : obsList)
  160. obs.update(msg);
  161. }
  162. }
  163.  
  164. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  165. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  166.  
  167. public interface IClientObs
  168. {
  169. public void update(String msg);
  170. }
  171.  
  172. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  173. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  174.  
  175. public class ClientGui implements ActionListener, KeyListener, IClientObs
  176. {
  177. private JLabel statusLbl;
  178. private JTextField chatTB, ipTB;
  179. private JTextArea txtArea;
  180. private JButton submitBtn, connectBtn, disconnBtn;
  181. private JList membList;
  182. private Container cont;
  183. private JFrame frame;
  184.  
  185. private Client client;
  186.  
  187. public ClientGui()
  188. {
  189. init("Client Chat");
  190.  
  191. frame.setBounds(100,100,600,500);
  192. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  193. frame.setVisible(true);
  194. }
  195.  
  196. private void init(String title)
  197. {
  198. frame = new JFrame(title);
  199. cont = frame.getContentPane();
  200. submitBtn = new JButton("Send");
  201. connectBtn = new JButton("Connect");
  202. disconnBtn = new JButton("Disconnect");
  203. txtArea = new JTextArea();
  204. chatTB = new JTextField(30);
  205. ipTB = new JTextField(16);
  206. statusLbl = new JLabel("Status:: Not Connected");
  207. membList = new JList(new String[]{"admin"});
  208. JLabel ipLbl = new JLabel("IP Address:");
  209. JPanel paneE = new JPanel();
  210.  
  211. txtArea.setEditable(false);
  212. paneE.setLayout(new BorderLayout());
  213.  
  214. Box boxS = new Box(BoxLayout.X_AXIS);
  215. boxS.add(chatTB);
  216. boxS.add(Box.createHorizontalStrut(2));
  217. boxS.add(submitBtn);
  218.  
  219. Box boxC = new Box(BoxLayout.Y_AXIS);
  220. boxC.add(new JScrollPane(txtArea));
  221. boxC.add(Box.createVerticalStrut(5));
  222.  
  223. Box boxE = new Box(BoxLayout.Y_AXIS);
  224. boxE.add(new JLabel("IP Address:"));
  225. boxE.add(ipTB);
  226.  
  227. Box boxI = new Box(BoxLayout.X_AXIS);
  228. boxI.add(connectBtn);
  229. boxI.add(Box.createHorizontalStrut(2));
  230. boxI.add(disconnBtn);
  231.  
  232. boxE.add(boxI);
  233. boxE.add(Box.createVerticalStrut(5));
  234.  
  235. paneE.add(boxE, BorderLayout.NORTH);
  236. paneE.add(membList, BorderLayout.CENTER);
  237.  
  238. cont.add(statusLbl, BorderLayout.NORTH);
  239. cont.add(boxC, BorderLayout.CENTER);
  240. cont.add(boxS, BorderLayout.SOUTH);
  241. cont.add(paneE, BorderLayout.EAST);
  242.  
  243. ipLbl.setHorizontalAlignment(SwingConstants.LEFT);
  244. boxE.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.RAISED));
  245. statusLbl.setPreferredSize(new Dimension((int)statusLbl.getSize().getWidth(), 30));
  246. membList.setBorder(BorderFactory.createLineBorder(Color.black));
  247. txtArea.setEditable(false);
  248.  
  249. connectBtn.addActionListener(this);
  250. disconnBtn.addActionListener(this);
  251. submitBtn.addActionListener(this);
  252. chatTB.addKeyListener(this);
  253. }
  254.  
  255. private void connect()
  256. {
  257. String ip = ipTB.getText();
  258. client = new Client(ip);
  259. client.addObserver(this);
  260. client.start();
  261.  
  262. connectBtn.setEnabled(false);
  263. disconnBtn.setEnabled(true);
  264. submitBtn.setEnabled(true);
  265. }
  266.  
  267. private void disconnect()
  268. {
  269. client.closeConn();
  270. client = null;
  271.  
  272. connectBtn.setEnabled(true);
  273. disconnBtn.setEnabled(false);
  274. submitBtn.setEnabled(false);
  275. }
  276.  
  277. private void sendData()
  278. {
  279. if (client != null && client.isConnected())
  280. {
  281. String msg = chatTB.getText();
  282. client.sendMsg(msg);
  283. }
  284. }
  285.  
  286. public void actionPerformed(ActionEvent e)
  287. {
  288. Object src = e.getSource();
  289. if (src == submitBtn)
  290. {
  291. sendData();
  292. }
  293. else if (src == connectBtn)
  294. {
  295. connect();
  296. }
  297. else if (src == disconnBtn)
  298. {
  299. disconnect();
  300. }
  301. }
  302.  
  303. public void keyPressed(KeyEvent e)
  304. {
  305.  
  306. }
  307.  
  308. public void keyReleased(KeyEvent e)
  309. {
  310.  
  311. }
  312.  
  313. public void keyTyped(KeyEvent e)
  314. {
  315. int key = e.getKeyChar();
  316. if (key == KeyEvent.VK_ENTER)
  317. sendData();
  318. }
  319.  
  320. public void update(String msg)
  321. {
  322. txtArea.append(msg);
  323. }
  324. }
  325. {code}
  326.  
  327. *Server-Side Files*
  328. {code}
  329. public class ConnClient extends Thread
  330. {
  331. private Socket conn;
  332. private ObjectOutputStream out;
  333. private ObjectInputStream in;
  334.  
  335. public ConnClient()
  336. {
  337. conn = null;
  338. out = null;
  339. in = null;
  340. }
  341.  
  342. public ConnClient(Socket pConn)
  343. {
  344. try
  345. {
  346. conn = pConn;
  347. if (conn.isConnected())
  348. {
  349. out = new ObjectOutputStream(conn.getOutputStream());
  350. in = new ObjectInputStream(conn.getInputStream());
  351. }
  352.  
  353. }
  354. catch(IOException e)
  355. {
  356. System.err.println("ConnClient:: ConnClient() -> " + e.getMessage() + "\n");
  357. }
  358. }
  359.  
  360. public String nextMsg()
  361. {
  362. String msg = "";
  363. try
  364. {
  365. msg = (String)in.readObject();
  366. }
  367. catch(IOException e)
  368. {
  369. System.err.println("ConnClient:: nextMsg() -> " + e.getMessage() + "\n");
  370. }
  371. {
  372. System.err.println("ConnClient:: nextMsg() -> " + e.getMessage() + "\n");
  373. }
  374. {
  375. System.err.println("ConnClient:: nextMsg() -> " + e.getMessage() + "\n");
  376. }
  377. return(msg);
  378. }
  379.  
  380. public boolean sendMsg(String msg)
  381. {
  382. boolean sentMsg = false;
  383. try
  384. {
  385. if (out != null)
  386. {
  387. out.writeObject(msg);
  388. out.flush();
  389. sentMsg = true;
  390. }
  391. }
  392. catch(IOException e)
  393. {
  394. System.err.println("ConnClient:: sendMsg() -> " + e.getMessage() + "\n");
  395. }
  396. return(sentMsg);
  397. }
  398.  
  399. public void closeConn() throws IOException
  400. {
  401. if (conn != null && in != null && out != null)
  402. {
  403. conn.close();
  404. in.close();
  405. out.close();
  406. }
  407. }
  408.  
  409. public String getIP()
  410. {
  411. return(conn.getRemoteSocketAddress().toString());
  412. }
  413.  
  414. public boolean isConnected()
  415. {
  416. return(conn.isConnected());
  417. }
  418. }
  419.  
  420. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  421. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  422.  
  423. public interface IServerObs
  424. {
  425. public void update(String msg);
  426. }
  427.  
  428. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  429. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  430.  
  431. public class ServerGui implements ActionListener, IServerObs
  432. {
  433. private JFrame frame;
  434. private Container cont;
  435. private JButton strBtn, stpBtn;
  436. private JTextArea console;
  437.  
  438. private Server server;
  439.  
  440. public ServerGui()
  441. {
  442. frame = new JFrame("Chat Server");
  443. cont = frame.getContentPane();
  444. strBtn = new JButton("Start Server");
  445. stpBtn = new JButton("Stop Server");
  446. console = new JTextArea();
  447.  
  448. strBtn.addActionListener(this);
  449. stpBtn.addActionListener(this);
  450.  
  451. Box b = Box.createHorizontalBox();
  452. b.add(strBtn);
  453. b.add(Box.createHorizontalStrut(3));
  454. b.add(stpBtn);
  455.  
  456. cont.add(new JScrollPane(console), BorderLayout.CENTER);
  457. cont.add(b, BorderLayout.SOUTH);
  458.  
  459. Toolkit kit = frame.getToolkit();
  460. Dimension d = kit.getScreenSize();
  461. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  462. frame.setBounds(d.width/4, d.height/4,
  463. ((int)(d.width/1.75)), ((int)(d.height/1.75)));
  464. frame.setVisible(true);
  465. }
  466.  
  467. public void actionPerformed(ActionEvent e)
  468. {
  469. Object src = e.getSource();
  470. if (src == strBtn)
  471. {
  472. if (server == null)
  473. {
  474. strBtn.setEnabled(false);
  475. stpBtn.setEnabled(true);
  476.  
  477. server = new Server();
  478. server.addObserver(this);
  479. server.start();
  480. }
  481. else
  482. {
  483. console.append("Console: Server is alread initiated.\n");
  484. }
  485. }
  486. else if (src == stpBtn)
  487. {
  488. strBtn.setEnabled(true);
  489. stpBtn.setEnabled(false);
  490.  
  491. server.shutdown();
  492. server = null;
  493. console.append("Console: Server has been stopped.\n");
  494. }
  495. }
  496.  
  497. public void update(String msg)
  498. {
  499. console.append("Console: " + msg + "\n");
  500. }
  501. }
  502. {code}
  503.  
  504. lol, sorry for so much code but I figured it would be necessary for context and figuring out where the problem is.

Report this snippet


Comments

RSS Icon Subscribe to comments

You need to login to post a comment.