server端无法正常发送数据给client端!client代码经工具没问题!

向云 2015-08-14 08:41:37
server接收来自client的消息,接收到非空消息后,发出指令‘2’,让client执行指定操作,结果必须关闭eclipse控制台后client才执行指令'2'对应命令,想让client收到服务器数据马上执行指定命令而不是关闭控制台后执行,client端没有问题,主要是服务器端java代码的问题,求高手帮忙哈!谢谢大家了!client使用c语言编写。
server代码:
package com.zeph.multiclient;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class MultiThreadServer extends Thread {
private Socket client;

public MultiThreadServer(Socket c) {
this.client = c;
}

public void run()
{
try
{
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
OutputStreamWriter out = new OutputStreamWriter(client.getOutputStream());
//BufferedReader sin=new BufferedReader(new InputStreamReader(System.in));
//out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);
String str = in.readLine();//接收信息
while (str!=null)
{
System.out.println(str);//将接收到的信息打印出来
out.write('2');//信息写入输出流
System.out.println("ok");
str=null;//清空数据,以跳出循环
}
}
catch (IOException e)
{
}
}

public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(1234);
while (true) {
MultiThreadServer mc = new MultiThreadServer(server.accept());
mc.start();
}
}
}


client代码:
/************************************************************
程序说明:
本程序运行后如果gprs模块找到服务商信号,就会连接指定的服务器。
1.将自己的51单片机的串口1连接到GSM的232接口
2.找到程序中前面的#define处,根据说明修改好自己的单片机配置.
3.使用浏览器打开网页http://www.ip138.com/。查询自己的外网ip地址。
4.在光盘中找到 调试工具\socket tool.exe 打开,协议类型:tcp服务器、ip地址本地端口默认。最后点击连接
5.下载程序
6.启动模块,等待信号灯闪烁变慢,如果模块和手机卡正常工作,服务器将收到模块发来的信息

*************************************************************/
#include <REG52.H>
#include <string.h>

#define uchar unsigned char
#define uint unsigned int

//以下是你的51单片机的晶振大小
#define FOSC_110592M
//#define FOSC_12M

//信号指示灯
sbit light1=P1^0;
sbit light2=P1^1;
sbit light3=P1^2;
sbit light4=P1^3;
sbit light5=P1^4;
sbit light6=P1^5;
sbit light7=P1^6;
sbit light8=P1^7;
sbit light9=P0^0;
sbit light10=P0^1;
sbit light11=P0^2;
sbit light12=P0^3;
sbit light13=P0^4;
sbit light14=P0^5;
sbit light15=P0^6;
sbit light16=P0^7;
sbit light17=P2^0;
sbit light18=P2^1;
sbit light19=P2^2;
sbit light20=P2^3;
sbit light21=P2^4;
sbit light22=P2^5;
sbit light23=P2^6;
sbit light24=P2^7;

//以下用于保存单片机收到模块发来的AT指令,通过这些指令单片机可以判断模块的状态
uchar GsmRcv[50] = {0}; //接收到的数据
uchar GsmRcvAt[50] = {0};//接收到的AT指令
uchar GsmRcvCnt = 0; //计数
uchar GsmAtFlag = 0; //AT命令接收标志位
uchar GsmRcvFlag = 0;

//注意,无论接收到信号还是发送完信号,都会进中断服务程序的
/*初始化程序(必须使用,否则无法收发),次程序将会使用定时器1*/
void SerialInti()//初始化程序(必须使用,否则无法收发)
{
TMOD=0x20;//定时器1操作模式2:8位自动重载定时器

#ifdef FOSC_12M //在这里根据晶振大小设置不同的数值初始化串口
TH1=0xf3;//装入初值,波特率2400
TL1=0xf3;
#else
TH1=0xfd;//装入初值,波特率9600
TL1=0xfd;
#endif //end of SOC_12M

TR1=1;//打开定时器
SM0=0;//设置串行通讯工作模式,(10位一部发送,波特率可变,由定时器1的溢出率控制)
SM1=1;//(同上)在此模式下,定时器溢出一次就发送一个位的数据
REN=1;//串行接收允许位(要先设置sm0sm1再开串行允许)
EA=1;//开总中断
ES=1;//开串行口中断
}

/*串行通讯中断,收发完成将进入该中断*/
void Serial_interrupt() interrupt 4 //串口中断4
{
uchar i = 0;

if(RI == 1) //收到信息
{

RI=0;//接收中断信号清零,表示将继续接收

GsmRcv[GsmRcvCnt] = SBUF;
// Uart1Send(tmp);
GsmRcvCnt++;
if(GsmRcvFlag==1)
{
for(i=0; i<50; i++)
{
GsmRcv[i] = 0;
}
GsmRcvFlag=0;
}
//收到了完整的AT指令,完整的AT指令是以0x0a 0x0d结尾的。故作此判断,在接收的过程中是否收到0x0a 0x0d
//收到完整AT指令后,GsmRcvAt[]数组从GsmRcvAt[0]开始重新接收AT指令
if(GsmRcv[GsmRcvCnt-2] == 0x0d && GsmRcv[GsmRcvCnt-1] == 0x0a && GsmRcvCnt >= 2)
{
//一旦收到0x0a 0x0d,就将数据保存起来。用户主函数的判断。
for(i=0; i<GsmRcvCnt; i++)
{
GsmRcvAt[i] = GsmRcv[i];
GsmRcv[i] = 0;
}
GsmRcvCnt = 0;
GsmAtFlag = 1;//收到了完整的at指令,通过这个标志位置1,这样主函数就知道去判断了。
}
else if(GsmRcvCnt >= 50)//因为内存有限,收到了50个字符还是没有看到0x0a 0x0d的话,就重新开始接收吧。
{
GsmRcvCnt = 0;
}

}
}


void Uart1Send(uchar c)//发送字符
{
SBUF=c;
while(!TI);//等待发送完成信号(TI=1)出现
TI=0;
}

//串行口连续发送char型数组,遇到终止号\0将停止,即将数据完整发送
void Uart1Sends(uchar *str)//发送字符串
{
while(*str!='\0')
{
SBUF=*str;
while(!TI);//等待发送完成信号(TI=1)出现
TI=0;
str++;
}
}

//延时函数大概是1s钟,不过延时大的话不准...
void delay_ms(uint ms) //11.0592MHZ下延时1ms
{
uint i;
uchar j;
for(i=0;i<ms;i++)
{
for(j=0;j<200;j++);
for(j=0;j<102;j++);
}
}
void Chu(uchar at[]) //GSM运行状况判断
{
while(GsmAtFlag == 0)
{
Uart1Sends(at);//设置sim300波特率
delay_ms(500);//延时1秒
while(GsmAtFlag == 0);
while(1)
{
if(!strstr(GsmRcvAt, "ERROR") )
{
break;
}
}//检测是否收到 CHINA MOBILE 服务商信息。如果收到证明是连接上网络了
}
GsmAtFlag = 0;
}
void main()
{
uchar i = 0;
SerialInti();
//判断是否启动完成
GsmAtFlag = 0;

Chu("AT\r\n");
light1=0;

Chu("ATI\r\n");
light2=0;

//检测信号
Chu("AT+COPS?\r\n");
light3=0;

Chu("AT+CSQ\r\n");
light4=0;

Chu("AT+CGDCONT=1,\"IP\",\"CMNET\"\r\n");
light5=0;

Chu("AT+CGCLASS=\"B\"\r\n");
light6=0;

while(1)
{
Uart1Sends("AT+CIPCSGP=1,\"CMNET\"\r\n");
delay_ms(500);//延时1秒
while(GsmAtFlag == 0);
break;
}
light7=0;
GsmAtFlag = 0;

Chu("AT+CGATT=1\r\n");
light8=0;

Uart1Sends("AT+CIPCLOSE\r\n"); //关闭连接
delay_ms(500);
light24=0;

Uart1Sends("AT+CIPSHUT\r\n"); //关闭移动场景
delay_ms(500);
light23=0;

Uart1Sends("AT+CLPORT=\"TCP\",\"2022\"\r\n");//发送指令指定本地端口
delay_ms(500);
light22=0;

while(1)
{
Uart1Sends("AT+CIPSTART=\"TCP\",\"121.42.15.225\",\"32906\"\r\n");
delay_ms(2000);
while(1)
{
if(GsmAtFlag == 1 && strstr(GsmRcvAt, "CONNECT OK"))//检测是否收到 CONNECT OK ,如果这连接成功
{
Uart1Sends("AT+CIPSEND\r\n");//开始准备发送数据
delay_ms(2000);
Uart1Sends("1");//向服务器发送的具体数据 "储物箱在线!可执行任务!"
delay_ms(2000);
Uart1Send(0x1a);//以0x1a结束
GsmAtFlag=0;
break;
}
}
while(1)
{
for(;strstr(GsmRcv,"2");)
{
GsmRcvFlag=1;
P0=1;
Uart1Sends("AT+CIPSEND\r\n");//开始准备发送数据
delay_ms(2000);
Uart1Sends("2ok");//向服务器发送的具体数据'储物箱已打开!'
delay_ms(2000);
Uart1Send(0x1a);//以0x1a结束
delay_ms(2000);
GsmAtFlag=0;
break;
}
for(;strstr(GsmRcv,"3");)
{
GsmRcvFlag=1;
P0=0;
Uart1Sends("AT+CIPSEND\r\n");//开始准备发送数据
delay_ms(2000);
Uart1Sends("3ok");//向服务器发送的具体数据'储物箱已关闭!'
delay_ms(2000);
Uart1Send(0x1a);//以0x1a结束
delay_ms(2000);
GsmAtFlag=0;
break;
}
}
}


} //解决重复发,无法发
//打开 关闭
...全文
221 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
向云 2015-08-16
  • 打赏
  • 举报
回复
特别感谢skgary一针见血地指出了我程序所在问题,更要感谢zhuangqingch(java攻城师)详细的解答,看了你的分析受益匪浅,谢谢!!!
zhuangqingch 2015-08-15
  • 打赏
  • 举报
回复
不好意思,Server端代码写错了,修正下:
Socket socket = server.accept();
            MultiThreadServer mc = new MultiThreadServer(socket);
            System.out.println("accept connect: " + socket.getInetAddress().getHostAddress());
            mc.start();
zhuangqingch 2015-08-15
  • 打赏
  • 举报
回复
谢邀,先说说楼主代码的主要问题: 1、传输数据时没有刷新缓冲,即flush 2、没有处理好阻塞IO的问题 采用Socket和ServerSocket处理网络数据传输时,需要请注意输入输出流的阻塞问题,如: 数据传输方面:client端给Server端发送数据时,如果没有flush,则Server端在read数据时,会一直处于阻塞状态(等client数据传完),相应的,如果Server端响应数据给client端write完后没有flush也会有同样的问题。 3、BufferedReader没有正确使用。如3楼所说的,你的client传送数据没有带换行(\n)或回车(\r),则in.readLine()会一直处于阻塞状态(等完整个的一行数据,如果判断完整,解析到\r\n时) 关于IO的相关知识,建议楼主可以深入学习下,希望我的回答能对楼主有所帮助,还有不懂的,欢迎追问!
zhuangqingch 2015-08-15
  • 打赏
  • 举报
回复
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class MultiThreadServer extends Thread {
    private Socket client;

    public MultiThreadServer(Socket c) {
        this.client = c;
    }

    public void run() {
        try {
            System.out.println(Thread.currentThread().getName() + " start");
            BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
            OutputStreamWriter out = new OutputStreamWriter(client.getOutputStream());
//            BufferedReader sin=new BufferedReader(new InputStreamReader(System.in));
//            out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);
            String str = in.readLine();//接收信息
            while (str != null) {
                System.out.println("server receive: " + str);//将接收到的信息打印出来
                out.write('2');//信息写入输出流
                out.flush();//写回client需要flush
                System.out.println("ok");
                str = null;//清空数据,以跳出循环
            }
            System.out.println(Thread.currentThread().getName() + " end");
            out.close();
        } catch (IOException e) {
        }
    }

    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(1234);
        System.out.println("server is start!");
        while (true) {
            MultiThreadServer mc = new MultiThreadServer(server.accept());
            System.out.println("accept connect: " + server.getInetAddress().getHostAddress());
            mc.start();
        }
    }
}
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class Client {
    public static void main(String[] args) {
        int i = 1;
        while (i < 100) {
            String clientName = "client" + i;
            try {
                Socket socket = new Socket("127.0.0.1", 1234);
                OutputStream out = socket.getOutputStream();
                String msg = "hello,world" + i + "\r";
                out.write(msg.getBytes());
                out.flush();//刷新缓冲区数据,发送给服务端
                System.out.println(clientName + " send: " + msg);
                InputStream in = socket.getInputStream();
                byte[] bytes = new byte[1024];//假定服务传回数据少于1024 byte
                int result = in.read(bytes);
                if (result > 0) {
                    System.out.println(clientName + "receive: " + new String(bytes));
                }
                System.out.println(clientName + " end!");
                Thread.sleep(2000);
                i++;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
skgary 2015-08-15
  • 打赏
  • 举报
回复

Uart1Sends("AT+CIPSEND\r\n");//开始准备发送数据
delay_ms(2000);
Uart1Sends("1");//向服务器发送的具体数据 "储物箱在线!可执行任务!"
        delay_ms(2000);
Uart1Send(0x1a);//以0x1a结束
GsmAtFlag=0;
break;
好像这里客户端发一个字符1,然后发了0x1a,肯定没发回车换行,所以你服务器侧去readLine肯定没返回。 改 byte [] buffer = new byte[2]; in.read(buffer) ......
skgary 2015-08-15
  • 打赏
  • 举报
回复
没空仔细看你的客户端的代码,简单来说,你先看一下到底是不是readLine没返回导致服务器没发,还是服务器的代码没flush。 估计客户端根本没有发换行回车的可能性更大一些,这样readline是不会返回的。

public void run() 
{
try
{
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
OutputStreamWriter out = new OutputStreamWriter(client.getOutputStream());
//BufferedReader sin=new BufferedReader(new InputStreamReader(System.in));
//out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);  
String str = in.readLine();//接收信息
while (str!=null) 
{
System.out.println(str);//将接收到的信息打印出来
out.write('2');//信息写入输出流
System.out.println("ok");
str=null;//清空数据,以跳出循环
}
} 
catch (IOException e) 
{
}
}
向云 2015-08-15
  • 打赏
  • 举报
回复
添加过这两个语句,但还是一样的效果!
hwxia 2015-08-15
  • 打赏
  • 举报
回复
out.flush()或out.close()
c_java_123 2015-08-15
  • 打赏
  • 举报
回复
in.newline()

62,614

社区成员

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

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