初识通信:什么是通信?什么是端口?
首先,我们来看看点对点聊天:
1.我们先创建一个服务器对象,为了能够同时存在多个客户端,我们选择了多线程操作;
public class Jtp { public static void main(String[] args) { Jtp cs = new Jtp() ; cs.setUpServer(9090) ; } public void setUpServer(int port){ try{ //建立绑定在指定端口上的服务器对象 ServerSocket server = new ServerSocket(port) ; System.out.println("服务器创建成功!" + port) ; //让服务区进入等待状态:阻塞状态 while(true){ Socket client = server.accept() ; System.out.println("客户端的Ip地址是"+client.getRemoteSocketAddress()); //调用处理连接对象的方法去处理连接对象 //创建一个线程对象是传入进入的连接 ServerThread st = new ServerThread(client) ; st.start() ;//启动这个线程,去处理连接 System.out.println("已启动了一个线程去处理这个连接对象了") ; } }catch(Exception ef){ ef.printStackTrace(); } } }
2.创建线程类,控制输入输出流
class ServerThread extends Thread{ private Socket client ; //线程对象要处理的连接变量 private OutputStream out ; //输出流对象 /* * 创建这个线程对象时,传入一个它要处理的连接对象 */ public ServerThread(Socket sc){ this.client = sc ; } //将发送消息的代码包装到一个方法中 public void sendMsg2Me(String msg) throws Exception{ byte[] data = msg.getBytes() ; out.write(data);//用输出对象发送 out.flush(); } public void run(){ //在线程run中调用处理连接的方法 try { processChat(this.client) ; } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } //处理方法执行完毕后,线程自己即退出 } //处理客户机进入的连接对象 private void processChat(Socket client) throws Exception{ //从连接对象上的到输入输出流对象 OutputStream out = client.getOutputStream(); InputStream ins = client.getInputStream(); String s = "皇妃是个SB" ; byte[] data = s.getBytes();//取得组成这个字符串的字节 out.write(data) ;//用输出对象发送数据 out.flush();//强制输出 //调用读取字符串的方法,从输入流中读取一个字符串 String inputS = readString(ins) ; while(!inputS.equals("bye")){ System.out.println("客户机说:" + inputS) ; s ="服务器收到:" + inputS +"\r\n" ; data = s.getBytes();//取得组成这个字符串的字节 out.write(data) ;//用输出对象发送! out.flush();//强制输出 inputS = readString(ins) ;//读取客户机的下一次输入 } s = "你好,欢迎再来!\r\n" ; data = s.getBytes(); out.write(data) ; out.flush(); client.close() ;//关闭与客户机的连接 } /* * 从输入流对象中读取字节,拼成一个字符串返加 * 如果读到一个字节值为13,则认为以前的是一个字符串 */ private String readString(InputStream ins) throws Exception{ //创建一个字符串缓冲区 StringBuffer stb = new StringBuffer() ; char c = 0 ; while(c!=13){ //遇到一个换行,就是一句话 int i = ins.read();//读取客户机发来的一个字节; c =(char) i ;//将输入的字节转换为一个char stb.append(c) ; } //将读到的字节组转换为字符串,并调用trim去掉尾部的空格 String inputS = stb.toString().trim(); return inputS ; } }
//以后我们读取的时候可以采用BufferedReader 对InputStream进行封装
例 :
BufferedReader brd = new BufferedReader(new InputStream(ins)) ;
brd.readLine();//读取一行字符串,以换行结束
@ 2.我们现在开始实现多人聊天,并加上界面:
我们首先要创建一个服务端,和一个客户端,然后客户端可以实例化很多的客户,然后通过服务器
来达到群聊的目的。
第一步:我们首先来写一个服务器:
(1)创建一个窗体类,并带有主函数
public class ServerJFrame extends JFrame{ private ChatServer f ; private JTextArea ji ;//显示框 private JTextArea jo ;//输入框 public static void main(String[] args) { new ServerJFrame().socketjf() ; } public void socketjf(){ this.setTitle("服务器"); this.setSize(600,600) ; this.setDefaultCloseOperation(3) ; this.setLocationRelativeTo(null) ; this.setLayout(null) ; JButton jb1 = new JButton("start") ; JButton jb2 = new JButton("send"); final JTextField jf1 = new JTextField(5) ; ji = new JTextArea(5,20) ; JLabel la =new JLabel("要发送的消息"); jo = new JTextArea(5,20); ji.setEditable(false) ; this.add(ji) ; this.add(la) ; this.add(jo); this.add(jb1); this.add(jf1) ; this.add(jb2); ji.setBounds(10, 20, 550, 200) ; la.setBounds(50, 230, 550, 20) ; jo.setBounds(10,250,550,100) ; jb2.setBounds(180,370,200,50) ; jb1.setBounds(50,450,200,50) ; jf1.setBounds(300,450,200,50) ; this.setVisible(true) ; ActionListener t = (new ActionListener(){//内部类实现 int t ; public void actionPerformed(ActionEvent e) { if(e.getActionCommand().equals("start")){ // System.out.println("dainifei") ; t = Integer.parseInt(jf1.getText()) ; ChatServer f = new ChatServer(t ,ji);//创建ChatServer类 f.start();//开始线程启动服务器 接收多个客户端 } if(e.getActionCommand().equals("send")){ String sd = jo.getText(); ji.append("客户端说: " +sd+"\t\n"); jo.setText(null) ; for(int i=0;i<SocketList.lt.size();i++){ ServerThread t = SocketList.lt.get(i); t.sendMessage("客户端说: " +sd) ; // t.StringRead(ins); } } } }); jb1.addActionListener(t); jb2.addActionListener(t); } }
(2)创建一个SocketList类来创建一个队列,储存客户的信息;我们可以采取静态方法,这样就会变得方便些;
/* * 静态队列,用于存储ServerThread对象 */ public class SocketList { public static ArrayList<ServerThread> lt= new ArrayList<ServerThread>(); public static void add(ServerThread s){ lt.add(s) ; } }
(3)创建服务器类:
public class ChatServer extends Thread{ private int port ; Socket socket ; ServerThread f ; private JTextArea ji ; int i=1 ; public ChatServer(int port,JTextArea ji ){ this.port = port ; this.ji= ji; } public void server(int port){ try { ServerSocket server = new ServerSocket(port); System.out.println("创建服务器"+port); while(true){ socket = server.accept(); System.out.println("客户的地址是"+socket.getRemoteSocketAddress()); ServerThread f = new ServerThread(socket,ji); f.start(); f.setUser("用户"+ i ); SocketList.add(f) ; i =i +1 ; } } catch (Exception e) { e.printStackTrace(); } } public void run(){ server(port) ; } }
在这里,每创建一个客户对象,我们就把它加到队列中去,并为其注上名字标识
ServerThread:
控制 多个客户的接收,输出消息;
/* * 这个线程主要用于接收多个客户端 */ class ServerThread extends Thread{ private OutputStream out ; private Socket socket ; private JTextArea ji ; private BufferedReader brd ; private InputStream ins ; private String user ; //接收从ServerJFrame中传来的 JTextArea对象,和从ChatServer传来的Socket对象 public ServerThread(Socket socket,JTextArea ji){ this.socket = socket ; this.ji = ji ; } public String getUser(){//我将用户名进行了封装,写了它的getter和setter方法 return this.user ; } public void setUser(String s){ this.user =s ; } //实现发送信息给用户,这个方法可以不用加入线程 public void sendMessage(String msg) { try { msg +="\r\n" ; this.out.write(msg.getBytes()) ; this.out.flush(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void run(){ processChat(socket) ; } //该方法实现从客户端接收信息然后对信息进行处理的操作 public void processChat(Socket socket){ try { //获得Socket的输入输出流对象 out = socket.getOutputStream(); ins = socket.getInputStream() ; brd = new BufferedReader(new InputStreamReader(ins));//对InputStream进行封装 String s = "欢迎你来"; sendMessage(s) ; out.flush(); StringRead(this.ins) ; while(!s.equals("bye")){ out.flush(); StringRead(ins) ; } s="再见,欢迎再来" ; sendMessage(s); out.flush(); socket.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } //从客户端接收信息的方法 public void StringRead(InputStream ins) throws Exception{ // StringBuffer sb = new StringBuffer(); // char c= 0 ; // while(c!=13){ // int t = ins.read(); // c =(char)t ; // sb.append(c) ; // } // String inputs = sb.toString().trim(); // return inputs ; String input = brd.readLine();//读出一行字符 System.out.println("kehuduan"+input); ji.append(user +"说 "+input+"\r\n");//将读到的信息传递到显示框 for(int i=0;i<SocketList.lt.size();i++){ ServerThread t = SocketList.lt.get(i);//运用队列将得到的信息发给所有客户端 t.sendMessage(user+"说 "+input) ; // t.StringRead(ins); } } }
这样我们已经基本完成了服务端,我们来测试一下:
这样,服务端就完成了
下面我们来实现客户端:
首先,同样的,我们写一个界面,主函数类:
public class RocketJframe extends JFrame{ private JTextArea ji ; private RocketServer fd ; private JTextArea jo ; public static void main(String[] args) { new RocketJframe().socketjf() ; } public void socketjf(){ this.setTitle("客户端"); this.setSize(600,600) ; this.setDefaultCloseOperation(3) ; this.setLocationRelativeTo(null) ; JButton jb1 = new JButton("start") ; JButton jb2 = new JButton("send"); final JTextField jt1 = new JTextField(10); final JTextField jt2 = new JTextField(10); this.setLayout(null) ; ji = new JTextArea(5,20) ; JLabel lb = new JLabel("输入IP地址") ; JLabel la =new JLabel("要发送的消息"); JLabel lc = new JLabel("输入端口号"); jo = new JTextArea(5,20); ji.setEditable(false) ; this.add(ji) ;//显示框 this.add(la) ;//发送消息的标签 this.add(jo);//输入框 this.add(jb1);//start按钮 this.add(jt1);//ip地址文本框 this.add(jt2) ;//端口号 this.add(jb2); //send按钮 this.add(lb) ;//"输入IP地址" this.add(lc) ;//"输入端口号" ji.setBounds(10, 20, 550, 200) ; la.setBounds(50, 230, 550, 20) ; jo.setBounds(10,250,550,100) ; jb2.setBounds(180,370,200,50) ; jb1.setBounds(180,420,200,50) ; lb.setBounds(10,420,100,50) ; lc.setBounds(460,420,100,50) ; jt1.setBounds(10, 500, 100, 50) ; jt2.setBounds(480, 500, 100, 50) ; this.setVisible(true) ; ActionListener t = (new ActionListener(){ public void actionPerformed(ActionEvent e) { f(e.getActionCommand().equals("start")){ String gh = jt1.getText(); int th = Integer.parseInt(jt2.getText()) ; fd = new RocketServer(gh,th,ji);//实例化RocketServer类 if(fd.server()){ fd.start(); //启动线程,接收服务器发来的信息 } } if(e.getActionCommand().equals("send")){ String msg = jo.getText() ;//取得输入框写入的信息 jo.setText(null) ;//设置写完后清空输入框 fd.sendMessage(msg);//将输入框的信息发送给服务器 } }}); jb1.addActionListener(t); jb2.addActionListener(t); } }
然后写一个输入输出流的线程类:
public class RocketServer extends Thread{ private int port ; private OutputStream out ; private Socket socket ; private BufferedReader brd; private JTextArea jt ; String ip ; String inputs ; //需要把ip地址,端口号,和文本框对象传过来 public RocketServer(String ip,int port,JTextArea jt){ this.ip = ip ; this.port = port ; this.jt =jt ; } public boolean server(){//判断是否能够连接上服务端 try { //连上了就创造Socket对象 socket = new Socket(this.ip,this.port) ; out = socket.getOutputStream() ; InputStream ins = socket.getInputStream() ; brd = new BufferedReader(new InputStreamReader(ins)); return true ; } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return false ; } public void run(){ while(true){ readFromServer(); } } public void readFromServer(){//读取服务端的信息的方法 try { String input = brd.readLine(); System.out.println("服务器"+input); jt.append(input + "\r\n") ; //将收到的信息传到显示框 } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void sendMessage(String msg) { //将信息发送给服务端的方法 try { msg += "\r\n"; out.write(msg.getBytes()) ; out.flush() ; } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
下面我们的客户端就做好了,可以看看效果:
其中,让我有点不解的就是接受数据问题,后来吧接受反倒线程中就成功的解决了。恩,我要讲的就这些了。下次继续图片的传输
相关推荐
- **群聊**:点对点聊天室程序可以通过扩展,支持多用户间的群聊功能,这需要更复杂的网络管理和同步机制。 - **文件传输**:除了文本消息,还可以添加文件传输功能,这需要考虑文件的分块传输、断点续传等问题。 ...
在IT行业中,网络通信是至关重要的一个领域,而基于socket的点对点聊天程序则是实现这一功能的基础。本文将深入探讨这个主题,讲解如何利用TCP协议通过socket接口创建一个简单的客户端-服务器架构的点对点聊天系统。...
Spring Boot整合websocket实现群聊,音频发送,点对点聊天,图片发送。 Spring Boot整合websocket实现群聊,点对点聊天,图片发送,音频发送。 Spring Boot整合websocket实现群聊,点对点聊天,图片发送,音频发送 ...
本项目“TCP/DUP实现群聊点对点聊天”利用C语言实现了基于TCP/IP协议的聊天应用,模拟了QQ的部分功能,提供了丰富的交互体验。下面将详细讲解其中涉及的关键知识点。 1. **TCP(Transmission Control Protocol)...
本项目“java QQ的源码对点聊天群聊”正是利用Java技术实现了腾讯QQ的核心功能,包括点对点(P2P)聊天和群聊,提供了一个完整的聊天系统,包含登录界面和主界面。以下是这个项目的重点知识点和技术细节: 1. **...
点对点聊天系统是一种基于网络通信技术的交互平台,它允许用户之间进行实时的信息交流,类似于QQ这样的社交软件。在实现这样一个系统时,我们需要关注以下几个关键知识点: 1. **网络编程**:点对点聊天系统的基础...
点对点聊天(P2P,Peer-to-Peer)是一种通信模式,其中每个参与者既是客户端又是服务器,可以相互通信并直接交换数据。在服务器端实现点对点聊天系统涉及多个关键技术点,以下将详细阐述这些关键概念和实现步骤。 1...
在这个“c#开发tcp点对点聊天案例”中,我们将深入探讨如何利用C#和TCP协议构建一个简单的点对点聊天系统。 首先,TCP的三次握手是确保可靠连接的关键过程。在TCP连接建立之前,客户端和服务器必须通过三次交互来...
综上所述,"点对点聊天vb.NET代码.rar"这个压缩包文件包含的源码很可能是用VB.NET实现的一个简单点对点聊天程序,它涵盖了网络编程、多线程、UI设计等多个方面的知识。通过学习和理解这个源码,开发者可以深入理解VB...
Linux 点对点聊天文件传输系统是一种在Linux操作系统环境下实现的通信工具,它允许用户进行实时聊天并交换文件。本系统利用了Linux的开源特性以及强大的网络编程能力,为用户提供了一种便捷、安全的文件传输方式。 ...
Java点对点聊天系统是一种基于Java编程语言实现的通信应用,允许用户之间进行实时的文本交流。这个系统的核心是利用了Java的Socket编程技术,它提供了在网络中建立连接和交换数据的能力。点对点(P2P)的概念意味着...
总结来说,magChat是一款专注于点对点聊天的工具,提供了一种方便的本地测试环境,同时也体现了P2P通信技术的优势。对于开发者来说,它是测试和演示通信功能的理想平台;对于普通用户,它提供了一个安全、私密的聊天...
在“单点聊天”中,通常涉及到一对一的私密对话。在这种场景下,WebSocket服务器需要维护用户之间的连接状态,确保消息被正确地发送到指定的接收者。这通常通过在服务器端存储用户的连接标识(如socketID)并关联...
Spring Boot作为Java生态中的微服务框架,提供了方便地集成WebSocket的功能,使得开发者能够轻松构建实时交互的应用,如群聊、点对点聊天以及发送图片和音频等富媒体消息。 首先,集成WebSocket到Spring Boot项目中...
3. **IP MSG功能**: IP MSG(IP Message)是指基于IP地址的点对点通信。应用通过获取并解析网络接口的IP地址,来识别和连接局域网内的其他设备。这种方式不需要服务器中转,减少了通信延迟,但限制于同一网络环境。 ...
在本项目中,"springboot+netty点对点即时通讯、聊天" 是一个利用Spring Boot和Netty构建的实时通信应用,旨在实现用户之间的高效、低延迟的对话功能。以下将详细介绍该项目所涉及的关键技术和知识点。 1. **Spring...
【描述】提到:"自己写的openfire插件,可记录一对一,会议室聊天记录,内附sql文件,数据库mysql,赚点积分。嘿嘿",这表明这个插件是由个人开发者编写的,可能并非官方提供,但依然能有效地实现聊天记录的存储。...
【TCP聊天室群聊+私聊】项目是一个基于TCP协议实现的在线聊天系统,它可以支持群聊和私聊功能,让多个用户通过客户端连接到服务器,进行实时的信息交流。在这个项目中,我们可以深入理解TCP协议的工作原理,以及如何...
【标题】"一键登录,实现群聊、私聊功能的java聊天室"涉及的主要知识点包括Java编程语言、网络通信机制BIO(Blocking I/O)、图形用户界面GUI以及多线程编程。下面将对这些关键点进行详细介绍。 1. **Java编程语言*...
本文将深入探讨一个基于MFC(Microsoft Foundation Classes)库构建的简单点对点聊天程序,它利用TCP(Transmission Control Protocol)协议实现通信,虽然并非尽善尽美,但足以让我们了解此类程序的基本架构与工作...