Java基础之聊天器

本文介绍了一个简单的局域网聊天器及画板应用的开发过程,包括服务器与客户端的搭建、数据传输机制及图形绘制功能的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这是刚开始学习java网络编程的时候做的一个东东,,局域网聊天器,可以在局域网内,和小伙伴聊天,共同画图(游戏原型)。先上图吧



 

一,首先讲解下基本知识,建立网络连接,你首先得有服务器和客户端,

1,服务器:ServerSocket s=new ServerSocket(n);这样就建立好一个端口号n的服务器,如果把你的电脑比作公寓,端口号类似于你的房间号。服务器创建好后,你得等待客户端连接,Socket so=s.accept();这样就能获取到连接进来的客户端(如果当前么有人连进来,他就会阻塞在当前,不会执行下面的代码),然后你就得获取他的输入输出流,用来传送和接收数据,InputStream is=so.GetinpputStream();Outputstream ou=so.getOutPutstream();

2,客户端:Socket s=new Socket("ip",端口号);ip就是你连接的那台服务器的电脑的ip地址,端口号就是你创建服务器的那个端口号,也就是说你得先找到公寓地址,然后再去找房间,这样就连接好了,同样的获取输入输出流,用来传送接收数据。

二,以上就是基本知识点,现在开始实例代码

首先看界面代码

 

public  class fu extends JFrame{
	public Test t=new Test();
	private static JTextArea jt3;
	public JTextField jt2;
	static Graphics gr;
public void UI(){
	this.setTitle("服务器");
	this.setSize(400,400);
	this.setLocation(400,200);
	this.setLayout(new FlowLayout(FlowLayout.LEFT));
	this.setDefaultCloseOperation(3);
	JButton jb1=new JButton("start");//启动服务器按钮
	this.add(jb1);
	JTextField jt1=new JTextField();//输入消息框
	jt1.setPreferredSize(new Dimension(40,30));
	this.add(jt1);
	JButton jb2=new JButton("send");//发送按钮
	this.add(jb2);
	 jt2=new JTextField();
	jt2.setPreferredSize(new Dimension(180,30));
	this.add(jt2);
	 jt3=new JTextArea();
	jt3.setPreferredSize(new Dimension(400,150));
	this.add(jt3);
	JPanel jp=new JPanel();
	jp.setPreferredSize(new Dimension(400,150));
	this.add(jp);
	this.setVisible(true);
	gr= jp.getGraphics();
	Test t=new Test();
	fhj fh=new fhj(this,t);
	jp.addMouseListener(fh);
	fujian f=new fujian(jt1,jt2,t);
	jb1.addActionListener(f);
	jb2.addActionListener(f);
}
public static void setjt3(String s){
	jt3.setText(s);
}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
       fu f=new fu();
       f.UI();
	}

}

 按下start触发事件fujian中的“start”

package First;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JTextField;

public class fujian  implements ActionListener {
	public JTextField jt1,jt2;
	public Test tt; 
	public fujian( JTextField jt1,JTextField jt2,Test tt ){
		this.jt1=jt1;
		this.jt2=jt2;
		this.tt=tt;
	}
	int co=0;
	@Override
	public void actionPerformed(ActionEvent e) {
	
		// TODO Auto-generated method stub
		if(e.getActionCommand().equals("start")){
			
			if(co==0){
			fuxian u=new fuxian(jt1,tt);
			u.start();
			co=1;
			}else{
				System.out.println("端口已经成功创建无需再创建");
			}
		}
		if(e.getActionCommand().equals("send")){
			for(int i=0;i<tt.l.size();i++){
				try {
					tt.l.get(i).qunfa(jt2.getText());
				} catch (Exception e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
		}
	}

}

 启动一个线程fuxian u=new fuxian(jt1,tt); u.start();来启动服务器

package First;

import javax.swing.JTextField;

public class fuxian extends Thread{
	public JTextField jt;
	public Test tt; 
public fuxian(JTextField jt,Test tt){
	this.jt=jt;
	this.tt=tt;
}
public void run(){
	int x=Integer.parseInt(jt.getText());
	tt.set(x);
}
}

 

启动服务器的具体方法是Test类中的set()方法

package First;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

import org.omg.CORBA_2_3.portable.OutputStream;

public class  Test {
public  ArrayList<Tx> l=new ArrayList<Tx>();
public void  set(int x) {
	//建立绑定在指定端口傻瓜的服务器
	ServerSocket se;
	try {
		se = new ServerSocket(x);
		System.out.println("服务器创建成功"+x);
		Socket c;
		//让服务器进入等待状态:
		while(true){
		c=se.accept();
		Tx t=new Tx(c,this);
		l.add(t);
		System.out.println("目前队列的长度是"+l.size());
		t.start();
	}
	}catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}

	}
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
	}

}

 其中public  ArrayList<Tx> l=new ArrayList<Tx>();是一个Tx类型的队列,用来存储Tx对象

c=se.accept();
Tx t=new Tx(c,this);
l.add(t);
一旦有客户连接就启动Tx线程,并且将Tx对象存储,现在来看下Tx的具体类容

package First;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.ArrayList;

public class Tx extends Thread {
	public DataInputStream Di;
	public DataOutputStream Do;
	public BufferedReader bf;
	public int j=0;
	public Socket c;
	public String name="",r;
    public java.io.OutputStream out;
	public Test t1;
    public InputStream in;
	public Tx(Socket c,Test t1) throws Exception {
		this.c=c;
		this.t1=t1;
		 in=c.getInputStream();
		 Di=new DataInputStream(in);
		out=c.getOutputStream();
		Do=new DataOutputStream(out);
	}
	public void qunfa(String s) throws Exception{	
      s +="\r\n";
	byte[] data=s.getBytes();
	String t=new String(data);
    System.out.println(t);
    Do.writeByte(1);
	Do.write(data);
	}
public  void jieshou() throws Exception{
	   //out=c.getOutputStream();
	   int k=Di.readByte();
  if(k==0){
		   int x1=Di.readInt();
		   int y1=Di.readInt();
		   int x2=Di.readInt();
		   int y2=Di.readInt();
		   System.out.println("接受成功");
		   fu.gr.drawLine(x1, y1, x2, y2);
		   for(int i=0;i<t1.l.size();i++){
			t1.l.get(i).Do.writeByte(0);
			t1.l.get(i).Do.writeInt(x1);
			t1.l.get(i).Do.writeInt(y1);
			t1.l.get(i).Do.writeInt(x2);
			t1.l.get(i).Do.writeInt(y2);
			//t1.l.get(i).Do.flush();
			System.out.println("传送成功");
			}
  }else if(k==1){
	   System.out.println("正在接受文字");
	   bf=new BufferedReader(new InputStreamReader(in));
	   r=bf.readLine();
		System.out.println(r);
		System.out.println("阅读完毕");
		fu.setjt3(r);
		String g="user"+r;
		g+="\r\n";
		byte[] e=g.getBytes();
		for(int i=0;i<t1.l.size();i++){
			t1.l.get(i).Do.writeByte(1);
			t1.l.get(i).Do.write(e);
			//t1.l.get(i).out.flush();
			System.out.println("执行了-----------"+i);
		System.out.println(r+"文字接受成功");
	}
		}else{
			System.out.println("eeeeeeeeeeeeeeeeeeeee"+k);
		}
	   }
public void X() throws Exception{
	while(true){
		System.out.println("主机接收");
		jieshou();
		}
}
public void run(){
	try {
		X();
	} catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
}
}

 由

public void run(){
try {
X();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
看出是线程开启 X();x()里面是个死循环 一直执行jieshou()方法

接收分为两种一种是接收图象,一种接收文字(自己定义的协议)

客户端连接之后开启线程接收,为什么要存储起来呢

这样就能对每一个客户端进行管理了,你可以向某一个客户端发送,或者全部发送(里面的qunfa方法)

上面是服务器接收,现在看服务器发送,这是fujian里面的方法,按下send之后,获取输入框上的东东,调用qunfa发送,其中有一个循环,就是把所有连接进来的客户端Tx对像取出来调用发送方法qunffa()

	if(e.getActionCommand().equals("send")){
			for(int i=0;i<tt.l.size();i++){
				try {
					tt.l.get(i).qunfa(jt2.getText());
				} catch (Exception e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}

 然后就是可以看下如何传送图像

package First;

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

public class fhj extends MouseAdapter{
	public Test tt;
	public fu f;
	public int  x1,x2,y1,y2;
	public fhj(fu f,Test tt){
		this.f=f;
		this.tt=tt;
	}
	public void mousePressed(MouseEvent e){
		x1=e.getX();
		y1=e.getY();
		
	}
	public void  mouseReleased(MouseEvent e){
		x2=e.getX();
		y2=e.getY();
		f.gr.drawLine(x1,y1,x2,y2);
		for(int i=0;i<tt.l.size();i++){
		try {
//			tt.l.get(i).Do.writeByte(1);
//			String s="画线成功";
//			s=s+"\r\n";
//			byte[] b=s.getBytes();
			//tt.l.get(i).Do.write(b);
			tt.l.get(i).Do.writeByte(0);
			tt.l.get(i).Do.writeInt(x1);
			tt.l.get(i).Do.writeInt(y1);
			tt.l.get(i).Do.writeInt(x2);
			tt.l.get(i).Do.writeInt(y2);
			System.out.println("发送成功-------------"+tt.l.size());
		
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}}
		
}
	}

 

上面是对画板的监听,首先传入tt.l.get(i).Do.writeByte(0);0,(自己定义的格式,接收方如果首先接收到0,就执行接收图片的方法),然后就是传入线条的四个坐标,(关于鼠标监听,前面的博客java基础画图板有说过),这样服务器这边就写完了

/******************************************下面开始客户端的接收与发送*********************************/

客户端和服务器的接收和发送差不多,所以不再啰嗦

界面

package First;

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
public class ku extends JFrame{
	static String s;
	static Graphics g;
	static JTextArea jt1;
	static JTextArea jt2;
	public void UI(){
		this.setTitle("客户端");
		this.setSize(400,400);
		this.setLocation(400,200);
		this.setLayout(new FlowLayout(FlowLayout.CENTER));
		this.setDefaultCloseOperation(3);
		JButton jb1=new JButton("登录");
		JButton jb2=new JButton("发送");
		 jt1=new JTextArea();
		jt1.setPreferredSize(new Dimension(380,100));
		jt2=new JTextArea();
		jt2.setPreferredSize(new Dimension(380,100));
		JPanel jp=new JPanel();
		this.add(jp);
		jp.setPreferredSize(new Dimension(380,100));
		this.add(jt1);
		this.add(jt2);
		this.add(jb1);
		this.add(jb2);
		this.setVisible(true);
		g=jp.getGraphics();
		kejian ke=new kejian();
		kbj kb=new kbj(this,ke);
		jp.addMouseListener(kb);
		jb1.addActionListener(ke);
		jb2.addActionListener(ke);
	}
	public  static void getjt2(){
		 s=jt2.getText();
	}
	public static void setjt2(){
		jt2.setText("");
	} 
public static void setjt1(){
	jt1.setText(s);
}
public static void setjt1(String st){
	jt1.setText(st);
}
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
ku t=new ku();
t.UI();
	}
}

 

然后是连接和接收的方法,

package First;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class kehu extends Thread{
	public int j=2;
public int i=0;
public BufferedReader bu;
public String ip;
public int pot;
public StringBuffer b=new StringBuffer() ;
public  InputStream in;
static  OutputStream out;
static DataInputStream Di;
static DataOutputStream Do;
//public kehu(String ip,int pot){this.ip=ip;this.pot=pot;}
public void login() throws Exception{
	Socket s=new Socket( "172.16.27.47", 9090);
	in=s.getInputStream();
	out=s.getOutputStream();
	Di=new DataInputStream(in);
	Do=new DataOutputStream(out);
	while(true){
		System.out.println("等待循环");
		js();
	}
}
public void js() throws Exception{
	System.out.print("客户端正在接受");
	int k=Di.readByte();
	if(k==0){
		int x1=Di.readInt();
		int y1=Di.readInt();
		int x2=Di.readInt();
		int y2=Di.readInt();
		ku.g.drawLine(x1, y1, x2, y2);
	}else if(k==1){
	bu=new BufferedReader(new InputStreamReader(in));
	String str=bu.readLine();
	ku.setjt1(str);
	System.out.println("设置窗体"+str);
}
}
public void run(){
	try {
		login();
	} catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
}
public static void main(String[] args) throws Exception{
	//new kehu().login("192.168.1.149", 9090);
}
}

 这是放送的方法

package First;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;

public class kejian implements ActionListener{
	public kehu k;
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		if(e.getActionCommand().equals("登录")){
			try {
				k=new kehu();
				k.start();
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}
		if(e.getActionCommand().equals("发送")){
			ku.getjt2();
			ku.setjt2();
			String st=ku.s;
			st+="\r\n";
			System.out.println(st+"-------客户端发送成功-----------");
			byte[] by=st.getBytes();
			try {
				k.Do.writeByte(1);
				k.out.write(by);
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}
	}

}

 画板发送的方法

package First;

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;

public class kbj extends MouseAdapter{
	public int i=0;
	public kejian ke;
	public ku kk;
	public int  x1,x2,y1,y2;
	public kbj(ku k,kejian ke2){
		this.ke=ke2;
		this.kk=k;
	}
	
	public void mousePressed(MouseEvent e){
		x1=e.getX();
		y1=e.getY();
		
	}
	public void  mouseReleased(MouseEvent e){
		x2=e.getX();
		y2=e.getY();
		try {
			ke.k.Do.writeByte(0);
			ke.k.Do.writeInt(x1);
			ke.k.Do.writeInt(y1);
			ke.k.Do.writeInt(x2);
			ke.k.Do.writeInt(y2);
			System.out.println("发送成功");
			ke.k.Do.flush();
		} catch (Exception e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		kk.g.drawLine(x1, y1, x2, y2);
		}
		
}

 源码已经上传,不懂之处可以留言,可以联系505860922

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值