您的位置:程序门 -> .net技术 -> c#



socket清除端口数据问题


[收藏此页] [打印本页]选择字色:背景色:字体:[][][]


socket清除端口数据问题[已结贴,结贴人:vbagcl]
发表于:2007-02-28 15:58:56 楼主
我用socket往服务器某个端口发送数据,服务器段接受数据后,将端口数据清空,怎么办呢?请高手指点!
发表于:2007-02-28 16:06:211楼 得分:0
需要清除吗?
发表于:2007-02-28 16:06:502楼 得分:0
我的接收数据的代码如下:
tltcplisten   =   new   tcplistener   (   port   )   ;   //private   static   tcplistener   tltcplisten;
tltcplisten.start   (   )   ;  
tcclient   =   tltcplisten.accepttcpclient   (   )   ;
nsstream   =   tcclient.getstream   (   )   ;   //private   static     networkstream   nsstream;   srread=new   streamreader(nsstream);     //private   static     streamreader   srread;  
while(   blistener   )   //循环侦听  
{  
      string   smessage   =   " ";
      try
      {
          smessage   +=   srread.readline();//
        }
    catch(system.exception   ex){}
    if   (   smessage   ==   "end "   )   //判断是否为断开tcp连接控制码  
      {  
          tltcplisten.stop();   //关闭侦听  
          nsstream.close();   //释放资源  
          srread.close();  
          ththreadread.abort();   //中止线程  
          return   ;  
          }
发表于:2007-02-28 16:07:373楼 得分:0
是啊,需要清除,怎么清除呢?请指教。
发表于:2007-02-28 16:12:364楼 得分:1
smessage   +=   srread.readline();//
这句相当于数据读完了。流里面的指针会下移。
发表于:2007-02-28 16:13:595楼 得分:0
可是,重新读的时候指针又回去啦,原来的数据又读出来啦
发表于:2007-02-28 16:16:546楼 得分:1
do
{
    smessage   +=   srread.readline();//
}
while(smessage   !=   "end ")
发表于:2007-02-28 16:19:317楼 得分:0
我的程序处理的过程是客户端不定时间往端口写数据,服务器端必须不断地从端口读数据,所以必须读后清除掉。
发表于:2007-02-28 16:27:358楼 得分:0
我以前做过类似的没事。
是不是发送的时候,上次的数据又发送了一次?
发表于:2007-02-28 16:28:509楼 得分:1
没用过tcpclient,但是我觉得应该把这两句也放到循环内

nsstream   =   tcclient.getstream   (   )   ;   //private   static     networkstream   nsstream;   srread=new   streamreader(nsstream);     //private   static     streamreader   srread;  
发表于:2007-02-28 16:36:5910楼 得分:1
不好意思,我上面说的不对

试试用seek方法移动到stream的指定位置
发表于:2007-02-28 16:37:1711楼 得分:0
因为客户端不定时地往服务器端口写数据,所以服务器要定时地从端口读取数据,如果服务器在读数据的时候,而客户端并没有写数据,由于上次客户端写的数据没有清除,服务器分不清当时的数据是客户端原来写的还是重新写的,因为客户端也可能重复写同样的数据,也可能写不同的数据,所以服务器在读完数据后把端口的数据清除掉就可以解决这个问题。
发表于:2007-02-28 16:38:4712楼 得分:0
服务器端每次在读数据的时候都要从头读啊
发表于:2007-02-28 18:41:2113楼 得分:1
在需要正式读取数据前,先判断缓冲区有多少数据(available属性),如果> 0,先把缓冲区数据读掉。然后再等到available属性> 0时候再读取你所需要的数据。
发表于:2007-02-28 18:46:0414楼 得分:0
对不起我理解错误。看你描述的情况是你的程序没有写好
发表于:2007-02-28 18:48:2715楼 得分:2
我提个思路,首先你客户端发送数据每个帧应该有个时间间隔,这个时间就是帧间间隔时间。服务器端接收数据应该根据这个帧间间隔来接收每一帧,而不是清空原来所有数据来接收
发表于:2007-02-28 19:16:1516楼 得分:0
不是啊,客户端发送数据不定时的,事件发生时才会向服务器发送数据,而事件的发生时随机的。应该能清空端口的数据吧?
发表于:2007-02-28 19:41:5417楼 得分:0
并且客户端发送的数据量很大,如果不清的话,那端口的数据量不是越积越多吗?
发表于:2007-03-01 00:02:1518楼 得分:1
客户端在每次发送完数据后    
调用streamwriter.flush()函数试下
发表于:2007-03-01 08:31:5119楼 得分:0
原来就有啊:
swwriter.writeline(this.textbox1.text   );//private   streamwriter   swwriter;   swwriter.flush();
发表于:2007-03-01 08:47:5120楼 得分:1
函数recv(   socket   s,   char   far   *buf,   int   len,   int   flags   )
参数flags的值可为0或msg_peek、msg_oob的组合;   msg_peek代表将资料拷贝到
使用者提供的   buffer,但是资料并不从系统的   input   buffer   中移走;0   则表示
拷贝并移走。

所以将最后一个参数置为0即可。
发表于:2007-03-01 09:17:4521楼 得分:5
我以前遇到过,结论给你:无法清空缓存里面的数据,这是系统维护的.如果缓存里面有3个,你只收了2个,那么2个popup,1个留在里面.所以自己要计算好.
发表于:2007-03-01 10:46:5222楼 得分:0
不会吧,太可怕啦,那数据不是越积越多,系统会越来越慢吗?
发表于:2007-03-01 12:00:5323楼 得分:5
数据不会堆积啊   ,指针会自己下移,前面的数据会自动清除
发表于:2007-03-01 12:04:5724楼 得分:6
数据不会堆积啊   ,指针会自己下移,前面的数据会自动清除

------------------------------------------------
你说的没错,但是如果你前一次没有取干净,那么就会留下垃圾数据,
一般缓存时8k,比如你有6k的垃圾数据,后面一次来了8k的数据,在缓存里面
其实只有2k的正常数据和6k的垃圾数据,那么你取一下8k的时候,怎么会不错哪?
所以要自己计算好,两边的数据格式是否一样
发表于:2007-03-01 12:06:0825楼 得分:2
不会吧,太可怕啦,那数据不是越积越多,系统会越来越慢吗?
----------------------------------------------------------
系统不会变慢,但是你取到的数据是错误的,造成你的程序crash,failure
发表于:2007-03-01 13:50:4926楼 得分:0
superxiaomm(小美)   ,老兄,您好!您说的没错,我用下面的代码:
private   void   connect_tcp_server(string   ipaddress,   int   port_str)
{
      ipaddress   ipremote   ;
        try  
          {  
ipremote   =   ipaddress.parse   (   ipaddress)   ;  
            }  
        catch   //判断给定的ip地址的合法性  
          {  
messagebox.show   (   "输入的ip地址不合法! "   ,   "错误提示! "   )   ;  
return   ;  
            }  
      iphostentry   iphost   ;  
      try  
      {  
        iphost   =   dns.resolve(   ipaddress   )   ; 
      }  
      catch   //判断ip地址对应主机是否在线  
      {  
          messagebox.show   ( "远程主机不在线! "   ,   "错误提示! "   )   ;  
          return   ;  
        }  
      string   shostname   =   iphost.hostname   ;  
      try  
      {  
      tcpclient   tcpclient   =   new   tcpclient(shostname,port_str);
        nsstream   =   tcpclient.getstream();
        swwriter   =   new   streamwriter(nsstream); }  
        catch  
        {  
messagebox.show   (   "无法和远程主机8000端口建立连接! "   ,   "错误提示! "   )   ;  
return   ;  
          }  

}
private   void   form1_load(object   sender,   system.eventargs   e)
{
      connect_tcp_server( "127.0.0.1 ",8000);
}

swwriter.writeline(this.textbox1.text   );//刷新当前数据流中的数据  
swwriter.flush();  
发送数据,第一次服务器能接收,第二次发送服务器接收的仍然是第一次的数据,发送第三次报错,急死啦,搞了两天啦,没有进展,老兄多帮忙!
发表于:2007-03-01 14:10:4127楼 得分:0
你说的没错,但是如果你前一次没有取干净,那么就会留下垃圾数据,
一般缓存时8k,比如你有6k的垃圾数据,后面一次来了8k的数据,在缓存里面
其实只有2k的正常数据和6k的垃圾数据,那么你取一下8k的时候,怎么会不错哪?
所以要自己计算好,两边的数据格式是否一样
-------------------------------------------------------
superxiaomm(小美),老兄!你说的“前一次没有取干净”是什么意思,能具体一些吗?
我刚才反复试了一下,刚开始发送没问题,但接收的总是前n次发送的累加和当前的数据,客户端发送很多次时,可能就是你所说的超过缓存,所以报 "无法写入“,怎么办,给我指点一下,多谢啦!
发表于:2007-03-02 08:50:4328楼 得分:2
我们当时出现这个问题,是由于编码格式的不同照成的.如发送端,编码以unicode8来发,接受端以unicodedefault来收.

这样,你看,unicodedefault认为每个字符都是2位byte,而unicode8不同.所以在计算应该收多少时候会错.
解决方法,统一格式,都用unicodedefault
发表于:2007-03-02 08:55:2829楼 得分:0
建议你用网上现有的传输类库.找一下,什么都有了,传文件,传消息.
发表于:2007-03-02 09:17:4130楼 得分:2
这是你的服务端接收代码有问题。前面我说了根据最小桢间间隔来接收。
发表于:2007-03-02 09:33:5031楼 得分:0
贴出你服务器端接收数据的代码
发表于:2007-03-02 09:41:1032楼 得分:0
superxiaomm(小美)   ,老兄,你好!我在客户端直接把数据写入服务器的端口,没有设置编码格式,在服务器端也没有设置编码格式,是直接读出来的。麻烦您帮我看一下下面我写的代码。另外,你说的在网上找传输类库,我也没有找到,如果你手头上有现成的能传给我吗,或者,麻烦你告诉我网址我自己下,也可以,谢谢啦!
我的email:vbagcl@sohu.com

客户端:
string   shostname   =   iphost.hostname   ;  
tcpclient   tcpclient   =   new   tcpclient(shostname,port_str);
nsstream   =   tcpclient.getstream();
swwriter   =   new   streamwriter(nsstream);

swwriter.writeline(this.textbox1.text   );//刷新当前数据流中的数据  
swwriter.flush();

服务器端:
tltcplisten   =   new   tcplistener   (   port   )   ;
tltcplisten.start   (   )   ;
tcclient   =   tltcplisten.accepttcpclient   (   )   ;
nsstream   =   tcclient.getstream   (   )   ;
srread=new   streamreader(nsstream);
smessage   +=   srread.readline();
发表于:2007-03-02 09:45:2333楼 得分:0
我在上面已经把服务器端的完整代码贴上去啦
发表于:2007-03-02 09:45:3434楼 得分:1
服务器段的,怎么不直接用socket   对象,自己手动控制数据流

tcplistener本身就是一个高级层次的包装。理解不好里面的机制,反倒很容易出错
发表于:2007-03-02 10:26:2635楼 得分:0
我刚开始的时候倒是用socket,但是,一接收就死掉啦,我的代码如下:
public   static   string   receive_message(string   ip_address,   int   port)
{
      iphostentry   lipa   =   dns.resolve(ip_address);
      ipendpoint   lep   =   new   ipendpoint(lipa.addresslist[0],   port);
      socket   s   =   new   socket(lep.address.addressfamily,   sockettype.stream, protocoltype.tcp);
      try
      {
          s.connect(lep);
        }
    catch   (system.exception     e)
      {
          string   msgerr   =   e.message   ;
          messagebox.show(msgerr);
        }  
            byte[]   bytes   =   new   byte[100];
      s.receive(bytes,   0,   s.available,   socketflags.none);

      return   bytes.tostring();
      s.shutdown(socketshutdown.both);
      s.close();
}

在系统启动的时候用下面的代码打开端口:
tltcplisten   =   new   tcplistener   (   port   )   ;  
tltcplisten.start   (   )   ;   //开始监听  
tcclient   =   tltcplisten.accepttcpclient   (   )   ;

我刚才说的一接收就死机,就是执行:
s.receive(bytes,   0,   s.available,   socketflags.none);
就死机啦
发表于:2007-03-02 10:51:0336楼 得分:0
关键在这里:

s.receive


应该是这么写

int   bytesrev   =   s.receive(bytes,   0,   bytes.length,   socketflags.none);

return   system.text.encoding.utf8.getstring(bytes,   0,   bytesrev);

你那么写,当然会卡死了

包括看了你之前的tcplistener的写法,   都漏洞太多了
发表于:2007-03-02 10:54:3337楼 得分:2



才看到,你还没加循环判断,一次就能接受全部数据?那是理想情况

byte[]   bytes   =   new   byte[1024];

int   bytesrev   =   0
string   msg   =   " ";
do
{
        bytesrev   =   s.receive(bytes,   0,   bytes.length,   socketflags.none);
        msg   +=   system.text.encoding.utf8.getstring(bytes,   0,   bytesrev);
}
while(bytesrev   >   0);
发表于:2007-03-02 10:55:0438楼 得分:10
什么原因不太清楚,我的接收部分是这样写的
//接收线程函数
private   void   receivedataarrived()
{
        int   lastbytesread   =   0;
        while   (true)
        {
                //默认50ms为每帧的最小帧间间隔
                for   (int   i   =   0;   i   <   50;   i++)
                {
                        thread.sleep(1);
                        application.doevents();
                }

                if   (client.available   >   lastbytesread)
                {
                        lastbytesread   =   client.available;
                }
                else
                {
                        //已经接收到完整一帧,进行读取处理
                        if   (lastbytesread   >   0)
                        {
                                byte[]   frame   =   new   byte[lastbytesread];
                                stream.read(frame,   0,   lastbytesread);
                                lastbytesread   =   0;
                                //处理该帧
                                ...          
                        }
                }
        }
}
发表于:2007-03-02 10:56:1839楼 得分:16
你说的没错,但是如果你前一次没有取干净,那么就会留下垃圾数据,
一般缓存时8k,比如你有6k的垃圾数据,后面一次来了8k的数据,在缓存里面
其实只有2k的正常数据和6k的垃圾数据,那么你取一下8k的时候,怎么会不错哪?
所以要自己计算好,两边的数据格式是否一样
---------------------------------------------
你可以一直读完,然后再检测数据.下面是我写的一个读取ftp服务器指令返回数据的方法
        private   string   getmessage()
        {
string   firstline   =   reader.readline();
if   (firstline   ==   null   ¦ ¦   firstline.length   ==   0)
throw   new   ioexception( "unexpected   null   reply   received ");

stringbuilder   reply   =   new   stringbuilder(firstline);

string   replycode   =   reply.tostring().substring(0,   3);

//   check   for   multiline   response   and   build   up
//   the   reply
if   (reply[3]   ==   '- ')
{
bool   complete   =   false;
while   (!complete)
{
string   line   =   reader.readline();
if   (line   ==   null)
throw   new   ioexception( "unexpected   null   reply   received ");

if   (line.length   >   3   &&   line.substring(0,   3).equals(replycode)   &&   line[3]   ==   '   ')
{
reply.append(line.substring(3));
complete   =   true;
}
else
{
//   not   the   last   line
reply.append( "\r\n ");
reply.append(line);
}
}   //   end   while
}
//   end   if
return   reply.tostring();
        }
发表于:2007-03-02 11:00:4240楼 得分:0
其实这个跟receive方法是一样的
发表于:2007-03-02 11:08:1441楼 得分:0
不过用receive方法不知道需要接收多少数据,才算是接收到完整一帧,我那样接收就不会出现前一次没有取干净会留下垃圾数据的情况,另外一种方法就象楼上一样,根据帧格式来判断接收完整的一帧数据,不过我的更简单,而且具有通用性。
发表于:2007-03-02 11:19:4442楼 得分:0
我的那个是专门处理ftp数据的
发表于:2007-03-02 11:34:5643楼 得分:0
moon1(静静的黎明)老兄,你好,我按照你的说法,把我的代码改写如下:
public   static   string   receive_message(string   ip_address,   int   port)
{
  iphostentry   lipa   =   dns.resolve(ip_address);
  ipendpoint   lep   =   new   ipendpoint(lipa.addresslist[0],   port);
  socket   s   =   new   socket(lep.address.addressfamily,   sockettype.stream, protocoltype.tcp);
  try
  {
s.connect(lep);
  }
  catch   (system.exception     e)
  {string   msgerr   =   e.message   ;}  
  
  byte[]   send_msg   =   encoding.ascii.getbytes( "this   is   a   test ");
  int   i   =   s.send(send_msg,   0,   send_msg.length,   socketflags.none);
  byte[]   bytes   =   new   byte[1024];
  int   bytesrev   =   0;
  string   msg   =   " ";
  do
  {
bytesrev   =   s.receive(bytes,   0,   bytes.length,   socketflags.none);
msg   +=   system.text.encoding.utf8.getstring(bytes,   0,   bytesrev);
  }
  while(bytesrev   >   0);
  return   msg;
  s.shutdown(socketshutdown.both);
  s.close();
}

程序启动的时候用下面代码打开端口,如果不用下面代码打开端口,程序运行到
s.connect(lep);
发生异常:由于目机器积极拒绝,无法连接
但是,先用下面代码打开端口,程序运行到:
bytesrev   =   s.receive(bytes,   0,   bytes.length,   socketflags.none);
就死机,为什么啊? 请指教!
多谢!


发表于:2007-03-02 20:08:1544楼 得分:0
好啦,问题解决啦,我可以结贴啦,总之,我感觉大家都很热心,可惜分数很少,很难分,只好每人一点,不好意思。不过,我好像感觉,端口的数据无需清空,只要读出后,自动清空的,我原来的问题是在服务器端把监听和读数据写在一起啦,大家可以看看我上面发的接收端的代码,后来,我把监听和收数据据分开写。但为什么把监听和接收数据写在一起后,收到的是前n次的累加和,我还是没想明白。


快速检索

最新资讯
热门点击