这是刚开始学习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