socket连接 cpu100%

rorom 2010-03-24 09:42:04
代码如下:
现在的情况是,可以正常连接并能正常返回数据,但是每调用一次(单人)cpu会达到50%,如果连续调用2次cpu接近100%.
在我的应用中,这个是多人同时调用的,并且频率不低.现在放出去已经让我的服务器都挂了.不得已暂时关闭了这个功能.希望高手指点迷津,谢谢~





import ...

//static Logger log = Logger.getLogger(SocketClient.class.getName()); // 日志记录信息
private String hostName;
private int portNum;
private int delaySecond; // 发文接收返回报文延时

public SocketClient() {
this.hostName = "192.168.5.6";
this.portNum = 52114;
this.delaySecond = 15000;
}

private Socket getSocket() {
Socket socket = null;
try {
socket = new Socket(hostName, portNum);
} catch (UnknownHostException e) {
System.out.println("-->未知的主机名:" + hostName + " 异常");
} catch (IOException e) {
System.out.println("-hostName=" + hostName + " portNum=" + portNum
+ "---->IO异常错误" + e.getMessage());
}
return socket;
}

public String sendMessage(String strMessage) {
String str = "";

String serverString = "";
Socket socket;
try {
socket = getSocket();
// socket.setKeepAlive(true);
if (socket == null) { // 未能得到指定的Socket对象Socket通讯为空
return "查询超时";
}
PrintWriter out = new PrintWriter(socket.getOutputStream());
out.write(strMessage);
out.flush();
BufferedReader in = new BufferedReader(new InputStreamReader(socket
.getInputStream()));
long sendTime = System.currentTimeMillis();
long receiveTime = System.currentTimeMillis();
boolean received = false; // 成功接收报文
boolean delayTooLong = false;
serverString = null;
while (!received && !delayTooLong) {
if (socket.getInputStream().available() > 0) {
// serverString = in.readLine();
char tagChar[];
tagChar = new char[1024];
int len;
String temp;
String rev = "";
if ((len = in.read(tagChar)) != -1) {
temp = new String(tagChar, 0, len);
rev += temp;
temp = null;
}
serverString = rev;
}
receiveTime = System.currentTimeMillis();
if (serverString != null)
received = true; // 字符串不为空,接收成功
if ((receiveTime - sendTime) > delaySecond)
delayTooLong = true; // 接收等待时间过长,超时
}

// in.close();
// out.close();
str = serverString;
if (delayTooLong){
//str = "2190"; // 超时标志为真,返回超时码
str="超时";
}
// if (
// ..}

in.close();
out.close();
str = serverString;
if (delayTooLong)
//str = "2190"; // 超时标志为真,返回超时码
str="超时";
if (!received)
//str = "2190";
str="超时";
socket.close();
} catch (UnknownHostException e) {
// log.error("---->出现未知主机错误! 主机信息=" + this.hostName + " 端口号="
// + this.portNum + " 出错信息=" + e.getMessage());
str = "2191";
// System.exit(1);
} catch (IOException e) {
// log.error("---->出现IO异常! 主机信息=" + this.hostName + " 端口号="
// + this.portNum + " 出错信息=" + e.getMessage());
e.printStackTrace();
str = "2191";
} catch (Exception e) {
str = "2177";
// log.error("---->出现未知异常" + e.getMessage());
} finally {
socket = null;
str.trim();
// log.info("--->返回的socket通讯字符串="+str);
}

return str;
}

}


...全文
333 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
hsf_1982 2010-03-24
  • 打赏
  • 举报
回复
楼主这样的程序很有问题啊。
1.直接从套接字读数据会导致阻塞。为了避免阻塞,所以使用轮询的方式,但是轮询时要加时间间隔的,Thread.sleep(10L),否则就是无聊的消耗CPU资源;
2.循环里缺个退出,“delayTooLong = true; // 接收等待时间过长,超时”,那超时了,是不是该退出了呢?
3.Socket中有超时属性,干嘛自己做呢?
当然使用NIO,对楼主而言可能还需要点时间。

sharke118 2010-03-24
  • 打赏
  • 举报
回复
class Recieve implements Runnable {

public void run() {

try {
while(g_flag){
String str = dis.readUTF();
System.out.println("user1接收到消息:" + str);
System.out.println(text_area.getText());
System.out.println(text_area.getText() + str + "\n");
text_area.setText(text_area.getText() + str + "\n");

if(str.matches("对方已经退出!")){
dis.close();
g_flag = false;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

类似于这种的 , 把while里面内容改成你的,然后在主程序里面
Recieve r = new Recieve();
Thread t = new Thread(r);
t.start();
就可以了
  • 打赏
  • 举报
回复
给你个参考的……



/**
*多线程socket服务端
* @author 49
*/
package socketThread;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
//import java.io.PrintWriter;
import java.net.*;
import java.util.concurrent.*;
import wcdjsrc.dbSocket;
import javax.swing.*;

public class serverSocket {
private int port=10000;
private ServerSocket serverSocket;
private ExecutorService executorService;//线程池
private final int POOL_SIZE=10;//单个CPU线程池大小

public serverSocket() throws IOException{
serverSocket=new ServerSocket(port);
//Runtime的availableProcessor()方法返回当前系统的CPU数目.
executorService=Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()*POOL_SIZE);
System.out.println("服务器启动");
}

public void service(){
while(true){
Socket socket=null;
try {
//接收客户连接,只要客户进行了连接,就会触发accept();从而建立连接
socket=serverSocket.accept();
executorService.execute(new Handler(socket));

} catch (Exception e) {
e.printStackTrace();
}
}
}

// public static void main(String[] args) throws IOException {
// new serverSocket().service();
// }

}

class Handler implements Runnable{
private Socket socket;
private dbSocket ds=null;
public Handler(Socket socket){
this.socket=socket;
}
private PrintStream getWriter(Socket socket) throws IOException{
OutputStream socketOut=socket.getOutputStream();
return new PrintStream(socketOut,true,"UTF-8");
}
private BufferedReader getReader(Socket socket) throws IOException{
InputStream socketIn=socket.getInputStream();
return new BufferedReader(new InputStreamReader(socketIn,"UTF-8"));
}
public String echo(String msg){
return "echo:"+msg;
}
public void run(){
try {
System.out.println("New connection accepted "+socket.getInetAddress()+":"+socket.getPort());
BufferedReader br=getReader(socket);
PrintStream pw=getWriter(socket);
String msg=null;
String pwwords="";
while((msg=br.readLine())!=null){


System.out.println(msg);//接收到的数据


pwwords = "leaderusertrue";
pw.print(pwwords);//返回给手机端的数据

// br.close();
// socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
if(socket!=null)
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 rorom 的回复:]

或者哪位高手帮我提供一个最简易的解决方式.因为这个功能不是最主要的.能用就行了.但至少能占我太多的资源.
[/Quote]
你不使用多线程,人访问多了肯定要挂掉呀……最简单的解决方式就是使用多线程来修改……
rorom 2010-03-24
  • 打赏
  • 举报
回复
或者哪位高手帮我提供一个最简易的解决方式.因为这个功能不是最主要的.能用就行了.但至少能占我太多的资源.
rorom 2010-03-24
  • 打赏
  • 举报
回复
我对Socket几乎是一窍不通,但是项目里有一个小功能是用这个的,我就找了一段代码稍微改了下.
但是,现在这个功能用的人多了,居然把服务器搞挂了.真是无奈.

而且这个Socket的服务端是不可见的.我也不知道里面是什么东西,现在的问题是用多线程能解决问题不?
sharke118 2010-03-24
  • 打赏
  • 举报
回复
事件监听好像也行(观察者模式)
sharke118 2010-03-24
  • 打赏
  • 举报
回复
为什么不用线程来做这个事情呢
chenliuyang 2010-03-24
  • 打赏
  • 举报
回复
大哥你wehile里没有阻塞啊
  • 打赏
  • 举报
回复
你没使用多线程???
rorom 2010-03-24
  • 打赏
  • 举报
回复
NIO是什么..
临远 2010-03-24
  • 打赏
  • 举报
回复
while循环就会导致100%,考虑NIO吧。

62,620

社区成员

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

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