由于需要做个一个CS的系统,需要实现服务器和客户端的交互,那么这个通讯的基本类就很重要了 为了写这个基本类 真是费了一番周折 。要把这个做好 多线程需要理解的比较好。因为 服务器需要一直监听客户端的请求,而客户端也要一直监听 服务器的请求。
首先是 客户端:
package client;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client implements Runnable{
private Socket client;
private String ip = "127.0.0.1";
private int port = 8888;
private ObjectOutputStream out;
//连接
public void conn(){
try {
client = new Socket(ip,port);
if(client.getOutputStream()!=null) {
out = new ObjectOutputStream(client.getOutputStream());
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//启动线程
public void run() {
try {
ObjectInputStream in = new ObjectInputStream(client.getInputStream());
boolean flag = true;
while(flag){
Object obj = in.readObject();
if(obj!=null){
String s = (String)obj;
System.out.println("收到服务器消息:" + s);
if(s.equals("shutdown")){
flag = false;
}
}
}
System.out.println("ByeBye!");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//向服务器发送object
public void sendMessage(Object obj){
//ObjectOutputStream out=null;
try {
out.writeObject(obj);
out.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
服务器端有两个类:
主类:
package server;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class MainServer implements Runnable{
private int port = 8888;
List arr = new ArrayList();
//初始化方法
public void init(int port) {
this.port = port;
}
public void run() {
try {
ServerSocket server = new ServerSocket(port);
System.out.println("--------服务器启动---------");
while (true) {
Socket socket = server.accept();
System.out.println("--------客户端连接---------");
String ip = socket.getLocalSocketAddress()+"";
ip = ip.substring(1,10);
ServerAccept acc = new ServerAccept();
acc.init(socket,ip);
arr.add(acc);//将客户端放入数组中
acc.start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
//遍历数组,对指定IP发送object
public void sendMessage(String ip,Object obj) {
for(int i=0;i<arr.size();i++) {
ServerAccept a = (ServerAccept)arr.get(i);
String temp = a.getIp();
if(temp.equals(ip)) {
try {
a.getOut().writeObject(obj);
a.getOut().flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
线程类:
package server;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
public class ServerAccept extends Thread {
//private ObjectInputStream in;
private ObjectOutputStream out;
private String ip;
private String s;
private Socket socket;
public void init(Socket socket,String ip) {
try {
this.socket=socket;
this.out = new ObjectOutputStream(socket.getOutputStream());
this.ip=ip;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//一直监听客户端发送到来的消息
public void run() {
boolean flag = true;
try {
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
while(flag){
Object obj = in.readObject();
if(obj!=null){
String s = (String)obj;
if(s.equals("关闭")){
flag = false;
continue;
}
System.out.println("客户端消息:" + s);
}
}
// System.out.println("ByeBye!");
} catch (IOException e) {
// TODO Auto-generated catch block
flag = false;
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
flag = false;
e.printStackTrace();
}
}
public String getIp() {
return ip;
}
public ObjectOutputStream getOut() {
return out;
}
public String getS() {
return s;
}
}
在这个过程中 主要遇到了 最令人 头疼的 java.io.StreamCorruptedException: invalid type code: AC 异常。
一直不明白怎么回事 后来才知道 原来是 ObjectOutputStream 流只可以对应,不可以生成多次,
当时我把 红色的那一段代码 放在了 while 里面 结果一直报错,只可以发送一次,第二次就不行,因为你又new 了一个 ObjectOutputStream 那是不可以的 同一个 socket。
还有一个异常就是 java.io.ObjectInputStream$BlockDataInputStream.peekByte 异常
这个意思我查阅了一下 原来是 到达了文件的末尾,程序却没有正常结束读取文件内容 也就是蓝色的这一段 会抛异常 因为无法终止while 。 后来我 要结束流的时候就发送消息“关闭” 然后就 关闭了。socket是面向连接的 所以终止任何一方都会异常吧 ,现在都是捕获到异常然后 关闭 呵呵呵 。不过应该有好的方法。 我毕竟写的很多缺陷了。
这个基本类 实现了监听,主要就是在于 线程中的 连个while 循环 在一直等待着对方的消息,也是这里不好处理。
希望大家提出意见 改进啊
测试类:
package client;
public class ClientTest {
public static void main(String []args) {
Client client = new Client();
client.conn();
new Thread(client).start();
client.sendMessage("我发送的消息!");
client.sendMessage("这也是我发送的消息!");
client.sendMessage("关闭");
}
服务器:
/*
* ServerForm.java
*
* Created on __DATE__, __TIME__
*/
package server;
import java.util.HashMap;
/**
*
* @author __USER__
*/
public class ServerForm extends javax.swing.JFrame {
/** Creates new form ServerForm */
public ServerForm() {
initComponents();
}
/*
* 创建server对象
*
*/
MainServer server = new MainServer();
//ServerTest ser = new ServerTest();
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
//GEN-BEGIN:initComponents
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jButton1 = new javax.swing.JButton();
jTextField1 = new javax.swing.JTextField();
jButton2 = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jButton1.setText("\u542f\u52a8\u670d\u52a1\u5668");
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton1ActionPerformed(evt);
}
});
jButton2.setText("\u53d1\u9001\u6d88\u606f");
jButton2.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton2ActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(
getContentPane());
getContentPane().setLayout(layout);
layout
.setHorizontalGroup(layout
.createParallelGroup(
javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(
javax.swing.GroupLayout.Alignment.TRAILING,
layout
.createSequentialGroup()
.addContainerGap(47, Short.MAX_VALUE)
.addGroup(
layout
.createParallelGroup(
javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jButton1)
.addGroup(
layout
.createSequentialGroup()
.addComponent(
jTextField1,
javax.swing.GroupLayout.PREFERRED_SIZE,
139,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(
18,
18,
18)
.addComponent(
jButton2)))
.addContainerGap()));
layout
.setVerticalGroup(layout
.createParallelGroup(
javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(
javax.swing.GroupLayout.Alignment.TRAILING,
layout
.createSequentialGroup()
.addContainerGap(76, Short.MAX_VALUE)
.addComponent(jButton1)
.addGap(70, 70, 70)
.addGroup(
layout
.createParallelGroup(
javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jButton2)
.addComponent(
jTextField1,
javax.swing.GroupLayout.PREFERRED_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(104, 104, 104)));
pack();
}// </editor-fold>
//GEN-END:initComponents
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
String s = jTextField1.getText();
server.sendMessage("127.0.0.1", s);
jTextField1.setText("");
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
new Thread(server).start();
}
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new ServerForm().setVisible(true);
}
});
}
//GEN-BEGIN:variables
// Variables declaration - do not modify
private javax.swing.JButton jButton1;
private javax.swing.JButton jButton2;
private javax.swing.JTextField jTextField1;
// End of variables declaration//GEN-END:variables
}
说明:
1,运行serverForm,点击启动服务器。
2,运行clientTest,启动一个客户端。
3,在form界面,输入字符串,点击发送,会发送给服务器,在控制台输出。
由于我用的是 MyEclipse 8.0 这个界面是生成的 如果版本低的话 可能要导架包哈 呵呵
分享到:
相关推荐
### 错误解析:Caused by: android.system.ErrnoException: write failed: ENOSPC (No space left ...通过以上的方法和技术手段,可以有效地避免因存储空间不足而导致的应用程序异常,提高用户体验。
它以较少的代码和最小化的网络流量为目标,使得其成为物联网(IoT)领域中最常采用的通信协议之一。 #### 一、Broker-ActiveMQ **ActiveMQ**是Apache出品的一个非常优秀的消息中间件,支持多种消息传输协议,包括...
NULL 博文链接:https://wilian.iteye.com/blog/1992365
"启动异常invalid constant type:15"是一种常见的Java异常,主要是由于Java类加载机制中的一个bug所引起的。在Java中,类加载器会将class文件加载到内存中,并将其转换成Java类对象。但是,在某些情况下,类加载器...
Java连接达梦数据库驱动dm_jdbc: ...dm_jdbc\Dm7Dictionary.jar dm_jdbc\Dm7JdbcDriver14.jar dm_jdbc\Dm7JdbcDriver15.jar dm_jdbc\Dm7JdbcDriver16.jar dm_jdbc\Dm7JdbcDriver17.jar dm_jdbc\dmgeo_1.6.jar ...
- cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'dubbo:application'. - schema_reference.4: Failed to read schema document '...
在Java编程环境中,图片处理是一项常见的任务,但有时可能会遇到“javax.imageio.IIOException: Unsupported Image Type”的错误。这个异常通常表示Java的`ImageIO`类库无法识别或支持所尝试读取或写入的图像格式。...
通过ServerSocket和Socket类,可以创建客户端和服务器端的通信连接。 10. **API的使用**:Java标准库提供了丰富的API,如Swing或JavaFX用于图形用户界面(GUI)开发,JDBC用于数据库操作,JAXP和DOM/SAX用于XML处理...
在使用Mybatis框架时,你可能会遇到`org.apache.ibatis.exceptions.PersistenceException`这样的异常。...记住,对于这类异常,详细阅读异常信息和日志是非常重要的,它们通常会给出问题的关键线索。
invalid interface type(解决方案).md
多线程Socket阻塞模式下通信的例子 BCB-Socket阻塞模式通讯测试(多线程) 作者:Sncel(地狱情人) QQ:6522203 指导:invalid(空心菜) QQ:309283 http://bcb.vicp.net 测试方法: 在单机上测试: 如果有多个客户...
使用@EnableDubbo启用dubbo, 配置dubbo.protocol.xxx相关属性,不设置dubbo.protocol.id,启动应用将会抛出异常. java.lang.IllegalStateException: Invalid name=“com.alibaba.dubbo.config.ProtocolConfig#0” ...
原因tomcat中使用的jdk低版和AES不兼容。 解决办法。 如在加密过程中出现下面异常: java.security.InvalidKeyException:illegal Key Size 请将两个jar文件按下列操作完成: 如果安装了JRE,将两个jar文件放到%JRE_...
ZK框架 :Ajax开发实战.5.rar
解析主机为: 112.125.43.138 已连接. 正等待响应. 220 Microsoft FTP Service USER 123000 331 Password required for 123. ...500 Invalid PORT Command. PASV 227 Entering Passive Mode (10,247,80,183,117,51).
修复了MqttAndroidClient会出现throw new IllegalArgumentException Invalid ClientHandle报错,而源github中代码未更新解决,所以经过重新编译,生成新的jar包,增加IllegalArgumentException异常处理,替换关联的...
2、可以转换,可以播放,但是有个异常:it.sauronsoftware.jave.EncoderException: video:0kB audio:1301kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.019516% 通过解读源码,在...
Invalid Subnet Mask(解决方案).md
发现问题 早上起来报错误,Jenkins打包到tomcat服务器,死活启动不起来,一些定时任务也没跑成功。 报错如下: org.apache.catalina.startup.ContextConfig.beforeStart Exception fixing docBase for context [/...
赠送jar包:httpcore-4.4.13.jar; 赠送原API文档:httpcore-4.4.13-javadoc.jar; 赠送源代码:httpcore-4.4.13-sources.jar; ... ... ...人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请放心使用。