一个手机上的网络聊天游戏(J2ME)

这是一个Client基于J2ME以及TCP/IP协议的简单的聊天程序,在本人模拟器上测试没问题,但并不保证真机上会出现问题。

代码以及整个游戏框架你可以拿来自由使用,但请注明出处。

(一)

这部分是程序Cilent端和Server端共用的一些类,之所以把它们拿出来单独写,是为了让整个程序的框架更清晰。

其实也就一个类、一个接口,但思想是一样的,或许你需要更多的类来让Client和Server共用,举个例子来说:如果你采用了“脏矩形技术”,那么可以把每个Item、每个Frame做个共享类放在这里。

Server接口:

public interface Server {
    public static final int PORT = 8042;
}

这个接口里很简单,之定义了一个端口号,以便于以后的程序修改和维护。

Message类:

听其名字就知道了,这个是消息类,因为无论是Client端还是Server端,其消息是能抽象出很多相似的东西的。

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

public class Message {
    public static final int NO_VALUE = -1;
    public static final int SIGNUP = 0;
    public static final int SIGNUP_ACK = 1;
    public static final int CLIENT_STATUS = 2;
    public static final int SERVER_STATUS = 3;
    public static final int ERROR = 4;
    public static final int SIGNOFF = 5;
    private int type;
    private String str;
    public static int player_id;

    public Message(int type,int player_id,String str) {
         this.type = type;
         Message.player_id = player_id;
         this.str = str;
    }
   
    public int getType() {
        return type;
    }

   public String getStr(){
     return str;
   }
   
    public void archive(DataOutputStream out) throws IOException {
        out.writeInt(type);
        out.writeInt(player_id);
        out.writeUTF(str);
        out.flush();
        System.out.println("***Client has send :"+type);
    }

   public static Message createFromStream(DataInputStream in) throws IOException {
        Message msg = new Message(in.readInt(), in.readInt(),in.readUTF());
        return msg;
    }

   public String toString() {
        return "Message: type # = " + type + ", player_id = "
               + player_id+", content = "+str;
    }

}

因为我们只是实现了简单的聊天功能,只是发送简单的字符给Server端,然后让其传送到各个Client端,因此功能比较简单,目的也仅仅用于学习,但你可以在此功能上增加更多的功能。

 

服务器端类

服务器端也很简单,就是开一个ServerSocket监听Client端的连接,如果有连接,就把此连接加入到一个List中。之所以这样处理, 是为了管理用户连接,比如将来你可能需要增加给特定的用户发送私人消息的功能,那么就可以从这个用户列表中寻找特定的用户进行发送。

连接建立以后利用一个单独的线程来进行通讯。

MultiPlayerServer类:

import java.io.IOException;
import java.net.ServerSocket;
import java.util.List;
import java.util.Vector;

public class MultiPlayerServer implements Server,Runnable{
    private List list;

    public MultiPlayerServer() {
        list = new Vector();
        Thread t2 = new Thread(this);
        t2.start();
    }
   
    public void distributeUpdate(int type,int player_id,String content) {
        ServerConnection conn;
        Message msg = new Message(type,player_id,content);
        for (int i = 0; i < list.size(); i++) {
            conn = (ServerConnection) list.get(i);
            conn.sendMessage(msg);
        }
    }

 

    public synchronized void removeConnection(ServerConnection conn) {
        list.remove(conn);
        System.out.println("removed connection for player " + conn.getPlayerID());
        System.out.println("connection list size is now " + list.size());
    }

 

    public void run() {
        ServerSocket socket;

        try {
            socket = new ServerSocket(PORT);
            System.out.println("multiplayer server listening @ " + PORT);

            for (; ; ) {
                    synchronized (this) {
                        list.add(new ServerConnection(socket.accept(),this));
                    }
                }
        } catch (IOException ioe) {
            System.out.println("*** MultiPlayerServer.run(): " + ioe);
        }
    }

}

ServerConnection类:

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.*;

public class ServerConnection implements Runnable {
    private MultiPlayerServer server;
    private Socket socket;
    private DataInputStream in;
    private DataOutputStream out;
    private int player_id;
    private Message err;
    private boolean done;
   
    public static Hashtable userList = new Hashtable();
    public static int player_count;

    /**
     * Create a new instance for use with game engine 'engine',
     * socket 'socket', and server 'server'.
     */
    public ServerConnection(Socket socket,MultiPlayerServer server) {
        this.server = server;
        this.socket = socket;
        done = false;
        Thread thread = new Thread(this);
        thread.start();
    }

    private synchronized void handleSignup(String str) {
        player_id = player_count++;
        if (player_id < 0) {
            System.out.println("ServerConnection.handleSignup(): engine refused player sign-up");
            return;
        }
        userList.put(new Integer(player_id),str);
        System.out.println("signed up player " + player_id);
        Message msg = new Message(Message.SIGNUP_ACK,player_id,"-1");

        try {
            msg.archive(out);
        } catch (IOException e) {
            System.out.println("***: could not send msg " + err);
        }
    }

    private void handleClientStatus(Message msg) {
        server.distributeUpdate(Message.SERVER_STATUS,player_id,userList.get(new Integer(player_id))+" 说 :"+msg.getStr());
    }

    public int getPlayerID() {
        return player_id;
    }

    /**
     * Send a message to the client connected to this instance
     */
    public synchronized void sendMessage(Message msg) {
        try {
            msg.archive(out);
        } catch (IOException e) {
            System.out.println("***: could not send msg " + msg);
        }
    }

    /**
     * main loop
     */
    public void run() {
        Message msg;

        try {
            in = new DataInputStream(socket.getInputStream());
            out = new DataOutputStream(socket.getOutputStream());

            while (!done) {
                msg = Message.createFromStream(in);
                switch (msg.getType()) {
                case Message.SIGNUP:
                 System.out.println("Server is handling : SIGNUP");
                    handleSignup(msg.getStr());
                    System.out.println("Server After : SIGNUP");
                    break;
                case Message.CLIENT_STATUS:
                 System.out.println("Server receive : CIENT_STATUS");
                    handleClientStatus(msg);
                    break;
                case Message.SIGNOFF:
                    break;
                default:
                    break;
                }
            }

            in.close();
            out.close();
            socket.close();
        } catch (Exception ioe) {
            System.out.println("*** ServerConnection.run(): " + ioe);
            server.removeConnection(this);
        }
        server.removeConnection(this);
        System.out.println("player " + player_id + " disconnected.");
    }

}

 

 

 

客户端类

客户端很简单,就是开一个线程处理用户的数据发送和接收,并做出相应的界面处理。

由于其简单,我就不再罗嗦,看代码:

MIDlet类:

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.TextField;
import javax.microedition.midlet.MIDlet;


/**
 * @author 孙东风
 *
 **/

public class ChatMIDlet extends MIDlet implements Runnable,CommandListener{
 
    private static final String SERVER_IP = "127.0.0.1";
    private Command exit = new Command("exit",Command.EXIT,1);
    private GameScreen screen;
    private DataInputStream in;
    private DataOutputStream out;
    private StreamConnection conn;
    private boolean done;
    private int player_id;
   
    public static Display display;

    Form login_form = new Form("登陆界面");
    TextField name_textfield = new TextField("请输入呢称 :","",10,TextField.ANY);
    Command loginCommand = new Command("登陆",Command.SCREEN,1);
    static String name;
   
 public ChatMIDlet() {
  super();
  login_form.append(name_textfield);
  login_form.addCommand(loginCommand);
  login_form.setCommandListener(this);
  display = Display.getDisplay(this);
 }


 protected void startApp(){
        try {
            conn = (StreamConnection) Connector.open("socket://"+SERVER_IP+":"+Server.PORT);
            in = new DataInputStream(conn.openInputStream());
            out = new DataOutputStream(conn.openOutputStream());
        } catch (IOException e) {
            closeConnection();
            System.out.println("*** could not connect to server: " + e);
            destroyApp(true);
        }
  Display.getDisplay(this).setCurrent(login_form);
 }
 
 public DataInputStream getInput(){
  return in;
 }
 
 public DataOutputStream getOutput(){
  return out;
 }

//关闭所有资源 
    private void closeConnection() {
        try {
            if (in != null) {
                in.close();
            }

            if (out != null) {
                out.close();
            }

            if (conn != null) {
                conn.close();
            }
        } catch (IOException e) {
            System.out.println(e);
        }
    }

 protected void pauseApp() {

 }


 protected void destroyApp(boolean bool){
  System.out.println("MidpTestClient.destroyApp()");
  Message msg = new Message(Message.SIGNOFF, Message.NO_VALUE,null);
  try {
            msg.archive(out);
        } catch (IOException e) {
        }

        closeConnection();
        Display.getDisplay(this).setCurrent(null);
 }

 public void handleStatus(Message msg){
  GameScreen.revStr = msg.getStr();
  screen.repaint();
 }
 
 public void handleError(){
     Message msg = new Message(Message.SIGNOFF, Message.NO_VALUE,null);

        try {
            msg.archive(out);
        } catch (IOException e) {
         e.printStackTrace();
        }
 }
 
 public void handleUnknown(Message msg){
  System.out.println("received unknown message: " + msg);
 }

 public void run() {

      Message msg;

         while (!done) {
             try {
                 msg = Message.createFromStream(in);
             } catch (IOException e) {
                 System.out.println("cant read message from stream");

                 continue;
             }

             switch (msg.getType()) {
             case Message.SERVER_STATUS:
              System.out.println("Client receive SERVER_STATUS");
                 handleStatus(msg);
              break;
             case Message.ERROR:
                 handleError();
                 break;
             default:
                 handleUnknown(msg);
                 break;
             }
         }
  
 }

 public void commandAction(Command cmd, Displayable g) {
        if (cmd == exit) {
            done = true;
            destroyApp(true);
            notifyDestroyed();
        }else if(cmd == loginCommand){
         if(name_textfield.getString().length() != 0){
          name = name_textfield.getString();
          Message msg = new Message(Message.SIGNUP,Message.NO_VALUE,name_textfield.getString());
          try{
           msg.archive(out);
           msg = Message.createFromStream(in);
           if (msg.getType() != Message.SIGNUP_ACK) {
                        System.out.println("*** could not sign up: " + msg);
                        destroyApp(true);
                    }
           
                    player_id = Message.player_id;
                    System.out.println("received sign-up ack, id = " + player_id);  
                    System.out.println("--------------1");
                    screen = new GameScreen();
                    screen.initialize(this, player_id);
                    done = false;
                    Thread thread = new Thread(this);
                    thread.start();
                    Display.getDisplay(this).setCurrent(screen);
          }catch(Exception e){
           System.out.println("*** could not sign up with server: " + e);
                    destroyApp(true);
          }
         }else{
          Alert alert = new Alert("警告","用户名和密码不能为空",null,AlertType.ERROR);
       alert.setTimeout(Alert.FOREVER);
       Display.getDisplay(this).setCurrent(alert);
               }
          }
    }

}
GameScreen类:

import javax.microedition.lcdui.*;

public class GameScreen extends Canvas implements CommandListener{

 public Form message_form = new Form("Send Message Form");
 public Command sendCommand = new Command("Send",Command.OK,1);
 public Command sendCommand2 = new Command("Send",Command.OK,1);
 public TextField content_textfield = new TextField("Content :","",10,TextField.ANY);
 public String content;
 
 public static String revStr = "null";
 
 public int player_id;
 ChatMIDlet chatmidlet;

 public GameScreen(){
  message_form.append(content_textfield);
  message_form.addCommand(sendCommand2);
  message_form.setCommandListener(this);
  this.addCommand(sendCommand);
  this.setCommandListener(this);
 }

 public void initialize(ChatMIDlet midlet,int player_id){
  this.chatmidlet = midlet;
  this.player_id = player_id;
 }
 
 protected void paint(Graphics g) {
   g.setColor(0x000000);
   g.fillRect(0,0,getWidth(),getHeight());
   g.setColor(0xffffff);
   g.drawString(revStr,0,0,Graphics.LEFT|Graphics.TOP);
 }


 public void commandAction(Command cmd, Displayable g) {
  if(cmd == sendCommand){
   System.out.println("CommandListenning this");
   ChatMIDlet.display.setCurrent(message_form);
  }else if(cmd == sendCommand2){
   content = content_textfield.getString();
   Message msg = new Message(Message.CLIENT_STATUS,player_id,content);
   try{
    msg.archive(chatmidlet.getOutput());
   }catch(Exception e){
    e.printStackTrace();
    System.out.println("Send Message Failed!");
   }
   ChatMIDlet.display.setCurrent(this);
  }
 }

}

后话:希望此文能为3G到来之前吹点热风,催化催化。

效果图如下:

输入呢称并传送到Server端

输入聊天内容

显示呢称和说话内容

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值