一个流用不同方法传输数据会有干扰吗?? 超急高分啊

yan119760463 2008-01-04 10:52:42
我在写一个网络五子棋程序,服务器端设置了两个线程,都用DataInputStream和DataOutputStream数据留,一个用writeInt和readInt负责处理棋子信息,一个用writeUTF和readUTF来处理聊天信息,但我发现两个同时开启两个线程的话,数据接收就会很不准确....可以说基本就没收到过正确的,到底怎么回事啊??

如果是线程设置的问题,请问怎么组织代码才合适呢??用两个内部类实现Runnable??
还有怎么样实现让连入的两个客户端分别使用不同颜色的棋子,并且当一个玩家没有落子时另一玩家不能落子呢??????

急啊....
...全文
123 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
jspxnet 2008-01-07
  • 打赏
  • 举报
回复
那就用两个端口得了
yan119760463 2008-01-06
  • 打赏
  • 举报
回复
我已经弄好聊天和下棋了,都用WRITEUTF()传递,再每个前面标记一个符号,服务器端判断是聊天或者是棋盘信息并调用相应方法处理

lihaifeng0412 2008-01-05
  • 打赏
  • 举报
回复
学习
yan119760463 2008-01-05
  • 打赏
  • 举报
回复
谢谢上面的各位,下面是我的服务器端代码(已经实现了棋子同步显示):
有两个私有类实现接口Runnable...注释掉的部分是用于聊天线程,如果把注释去掉后就会出现混乱,连下棋的线程都不行了....

因为要交上去了很急啊...帮忙改改的高手高分相送
public class GobangServer extends JFrame
{
private ServerSocket serversocket;
private boolean isStart = false;
private JTextArea 服务器 = new JTextArea();
private JButton 清空=new JButton("清空服务器");
private JButton 信息=new JButton("服务器信息");
private int index = 0;

//ArrayList<Client> clients = new ArrayList<Client>();
Client[] clients=new Client[2];
//Chat[] chats=new Chat[2];

//服务器界面 \
public GobangServer(String title)
{
this.setLayout(null);
Container content=this.getContentPane();
服务器.setEditable(false);
服务器.setBackground(Color.BLACK);
服务器.setForeground(Color.WHITE);
服务器.setBounds(0,0,280,210);
this.add(服务器);

清空.addActionListener(new ButtonAction());
清空.setBounds(150,215,100,25);
this.add(清空);
信息.addActionListener(new ButtonAction());
信息.setBounds(20,215,100,25);
this.add(信息);

this.setResizable(false);
this.setSize(280,280);
this.setLocation(400,200);
this.setTitle(title);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
serverMonitor();
}

//接收客户端socket
public void serverMonitor()
{
try
{
serversocket = new ServerSocket(9222,2);
isStart = true;
}
catch (IOException e)
{

e.printStackTrace();
}

try
{
//启动两个线程
while(isStart)
{
Socket socket = serversocket.accept();
Client c = new Client(socket,index);
//clients.add(c);
clients[index]=c;
//Chat ch=new Chat(socket);
//chats[index]=ch;
index ++;
服务器.append(socket.getInetAddress().getHostAddress()+"连接到"+index+"玩家\n");
new Thread(c).start();
//new Thread(ch).start();
}
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
try
{
serversocket.close();
}
catch (IOException e)
{

e.printStackTrace();
}
}

}

public static void main(String args[])
{
GobangServer Server = new GobangServer("五子棋服务器");
}

private class ButtonAction implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==清空)
{
服务器.setText("");
}
if(e.getSource()==信息)
{
try
{
服务器.setText("服务器开始信息:\n"
+ "IP:"+InetAddress.getLocalHost() + "\n"
+ "端口"+serversocket.getLocalPort() + "\n");
}
catch (UnknownHostException e1)
{
e1.printStackTrace();
}
}

}

}
//聊天线程
/*private class Chat implements Runnable
{
DataInputStream input = null;
DataOutputStream output = null;
boolean isStart = false;
Socket clientsocket = null;

Chat(Socket clientsocket)
{
this.clientsocket = clientsocket;
try
{
input = new DataInputStream(clientsocket.getInputStream());
output = new DataOutputStream(clientsocket.getOutputStream());
}
catch(IOException e)
{
e.printStackTrace();
}

isStart = true;
}
public void sendToClient(String str)
{
try
{
output.writeUTF(str);
output.flush();

}
catch(IOException e)
{
//网络面板.textarea1.append(clientsocket.getInetAddress().getHostAddress()+" exited \n");
}
}
public void run()
{
try
{
while(isStart)
{
String str = input.readUTF();
System.out.println(str);
for(int i=0;i<chats.length;i++)
{
Chat ch = chats[i];
ch.sendToClient(str);
}
}
}
catch(EOFException e)
{
chats[index]=null;
//clients.remove(this);
System.out.println("client closed");
}
catch(SocketException e)
{
System.out.println("client closed");
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
try
{
if(clientsocket != null) clientsocket.close();
if( input!= null) input.close();
if(output != null) output.close();
}
catch(IOException e)
{
e.printStackTrace();
}
}

}
}*/

//棋子传输
private class Client implements Runnable
{

DataInputStream in = null;
DataOutputStream out = null;

Socket socket = null;
boolean isStart = false;

int serverinfo;
int clientinfo;
int numX;
int numY;
char startcolor;
int color;
int curplayer;
int[][] chesse=new int[15][15];


Client(Socket socket,int num)
{
//决定先手颜色,第一个连接进入的服务器是a,通过writeChar传递给客户端,客户端转为1代表黑
startcolor=(num == 1 ? 'a' : 'b');
this.socket = socket;
try
{
in = new DataInputStream(socket.getInputStream());
out = new DataOutputStream(socket.getOutputStream());
}
catch(IOException e)
{
e.printStackTrace();
}
isStart = true;
}

public synchronized void sendToEveryClient(int clientinfo)
{
try
{
out.writeInt(clientinfo);
}
catch(IOException e)
{
clients[index]=null;
if(index>0)
index--;
else index=0;
服务器.append(socket.getInetAddress().getHostAddress()+" 退出\n");
}
}

public void run()
{
try
{
out.writeChar(startcolor);

while(isStart)
{
clientinfo = in.readInt();
if(clientinfo < 2240)
{
/分解从客户端传上来的代表棋盘上棋子的二维数组以及棋子颜色,传递c公式是1000*color+row*15+col
numX=clientinfo%1000/15;
numY=clientinfo%1000%15;
color=clientinfo/1000;
chesse[numX][numY]=color;
}

for(int i=0;i<clients.length/*.size()*/;i++)
{
Client client = clients[i];//clients.get(i);
client.sendToEveryClient(clientinfo);//str);
}
}
}
catch(EOFException e)
{
clients[index]=null;

服务器.append(socket.getInetAddress().getHostAddress()+"退出\n");
}
catch(SocketException e)
{
服务器.append(socket.getInetAddress().getHostAddress()+"退出\n");
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
try
{
if(socket != null) socket.close();
if(in != null) in.close();
if(out != null) out.close();
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
}
}
goodmrning 2008-01-05
  • 打赏
  • 举报
回复
顶!!!!!!!!!!!!1
网络咖啡 2008-01-05
  • 打赏
  • 举报
回复
你如何知道应该是readInt还是readUTF呢?

需要设计一个简单的协议吧
newflypig 2008-01-05
  • 打赏
  • 举报
回复
首先提示你使用OOP思想中的多态性处理这些复杂的网络传输问题
建立一个Message的父类,建议设置为abstrct类型,其中有一个虛函数叫AnswerMessage,表示解析这个消息的响应方法。
继承两个子类,一个是ConnectMessage还有一个是ChessMessage,实现AnswerMessage方法,当然两种不同的消息对应不同的响应方法。
A-B机通信
A发送ConnectMessage的序列化对象给B(UDP或者TCP,参考:网络传输序列化对象)
示例代码:
ConnectMessage cm = new ConnectMessage(senderid, senderNickname, scretmsg);

ByteArrayOutputStream byteStream = new ByteArrayOutputStream(1024);
ObjectOutputStream os = null;
byte sendBuf[] = (byte[])null;
DatagramSocket ds = null;
DatagramPacket dp = null;
try
{
os = new ObjectOutputStream(byteStream);
os.writeObject(cm);
sendBuf = byteStream.toByteArray();
ds = new DatagramSocket();
dp = new DatagramPacket(sendBuf, sendBuf.length, InetAddress.getByName(ipAddress), portAddress);
ds.send(dp);
ds.close();
}
catch(IOException e)
{
e.printStackTrace();
}
//当然,你也可仿照这个ConnectMessage发包过程做出其他的Message

B接受到流以后反序列化:
示例代码:
 ObjectInputStream s = null;
Message msg = null;
do
{
try
{
byte buf[] = new byte[1024];
DatagramPacket dpReceive = new DatagramPacket(buf, 1024);
dsReceive.receive(dpReceive);
s = new ObjectInputStream(new ByteArrayInputStream(dpReceive.getData()));
msg = (Message)s.readObject();
}
catch(Exception e)
{
e.printStackTrace();
}
AnswerMessage(msg);
} while(true);
private void AnswerMessage(Message msg)
{
msg.AnswerMessage();
}

这样做的好处在于你以后可以扩展出很多Message的子类,而不必到处修改源代码,因为所有Message的解析语句都是一个私有函数:AnswerMessage(msg)来处理,这个函数只是调用各种Message的AnswerMessage()方法,所以以后添加子Message类的时候,只需给每个Message写上响应的AnswerMessage()方法即可。这就是程序的多态性。

建议你采用这样的方法,而不是多个线程同时监听的方法来处理传输流,这种方法只需要一个TCP或者UDP线程来循环监听,而且使用对象序列化的技术来封装所传输的流,保证了流的互不干扰性
yan119760463 2008-01-05
  • 打赏
  • 举报
回复
恩..4楼的高手啊...只是小弟现在还没能力理解

我听说可以在服务器端做标记,记下棋子信息和聊天信息然后分别处理...想问下怎么个标记法
老紫竹 2008-01-05
  • 打赏
  • 举报
回复
棋子颜色也一样了
1 你可以在2面做计数器,单数的时候显示黑子,双数显示白子
2 你可以在传输的数据里面做标识,1=黑子,0=白子,和前面的标识是棋子信息还是聊天信息一样的原理

不能落子?

计数器等于单数,该黑方下子,自己这面猜先是白棋,对于落子事件不予处理就可以了。
老紫竹 2008-01-05
  • 打赏
  • 举报
回复
一个流,你要传输不同的信息,你必须把信息作一下标识。比如第一个byte是1, 代表后面是棋子信息,是0为聊天信息
当然,如果你用xml封装就更好了。

建议,下子和聊天分开处理,2个流,各自调试和运行,互不干扰。类也分开。
zhengguo07q 2008-01-05
  • 打赏
  • 举报
回复
4楼是高手,OO大牛啊。

我想楼主可能想错了 ,流的那些方法不能区别出读的东西的~~~~他只是按照方法对字节进行区分。

对象序列化用对象来区分不错,或者设置2个tcp连接吧 呵呵~~不知道对不对
frilly 2008-01-05
  • 打赏
  • 举报
回复
最好分开处理

62,623

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧