| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2968 人关注过本帖
标题:异步tcp通讯程序中读写文件的问题--第一次发帖请多关照
只看楼主 加入收藏
jingzhao22visa
Rank: 1
等 级:新手上路
威 望:1
帖 子:343
专家分:0
注 册:2006-8-10
收藏
 问题点数:0 回复次数:48 
异步tcp通讯程序中读写文件的问题--第一次发帖请多关照
刚进公司实习,被分配做socket通讯的程序。实在搞不定,请大家帮忙。

情况:
程序中已经实现了C/S之间的信息发送与接收,收发无误。但是现在要求要将收到的数据放入一个.dat文件。我所使用的收发全部是异步调用。例如BeginConnect,BeginReceive。
部分程序代码如下:
public unsafe void OnReceiveData(IAsyncResult ar)
{ Sock = (Socket)ar.AsyncState;
try
{ int nBytesRec = Sock.EndReceive(ar);
if (nBytesRec > 0)
{
。。。。。。。。。。。。。
string ss = Encoding.BigEndianUnicode.GetString(Receive_Buffer, 0, nBytesRec);
listBox_Receive.Items.Add(ss);
AddintoFile(ss);///在此处调用一个函数将收到的字符串写入文件。
Sock.BeginReceive(Receive_Buffer, 0, Receive_Buffer.Length,
SocketFlags.None,
new AsyncCallback(OnReceiveData),
Sock);
}


private unsafe void AddintoFile(string ss) //struct结构在最底下。
{
Test_Struct data;
byte* p;
char[] bt;
IntPtr ip;
string strV = ss;

bt = strV.ToCharArray();
data.tel_id = 99887;
data.test_data = 99999;
//fixed(byte * t=data.Telegram)
//{
//byte* tempt = t;
System.Runtime.InteropServices.Marshal.Copy(bt, 0, (IntPtr)data.Telegram, bt.Length);

p = (byte*)&data;

try
{
stlc.AddToHead(ref *p, sizeof(Test_Struct), 1);
}
*********************************************************
stlc.AddToHead(ref *p, sizeof(Test_Struct), 1);
此处的AddToHead函数是别人给的一个dll里面的函数
ref *p 引用的byte数组。即是要写入文件的bytes
sizeof(Test_Struct) 要写进去的bytes的长度
这个函数经过测试,是可以用的。当然是在单线程的
工作环境下。在这个异步调用的程序代码下,我经过
设置断点,只能看到确实执行了该句插入,也没有抛出异常。
但是就是文件里面写不进去。
我查了一些东西,可能是因为垃圾回收的问题,需要
将指针固定。但是固定指针的时候一直报错。fixed()
语句中一直不能用,说不能引用固定长度的指针。
p = (byte*)&data; 。(IntPtr)data.Telegram
使用fixed的时候就这两个地方出错。
有没有人帮忙看一下。

如果没有说清楚,我再补充。
*********************************************************
catch (Exception et)
{
MessageBox.Show(et.Message);
}
// }

strV = string.Format("After add data. total {0} telegrams in list", stlc.Size);
MessageBox.Show(strV);


}

private unsafe struct Test_Struct
{
public int tel_id;
public fixed byte Telegram[2048];
public int test_data;
}
搜索更多相关主题的帖子: tcp 异步 通讯 发帖 
2006-08-10 09:27
chenjin145
Rank: 1
等 级:禁止访问
帖 子:3922
专家分:0
注 册:2006-7-12
收藏
得分:0 
先show一下ss 看看到底有沒傳個string進去,確認錯誤在哪塊



p指向struct中的Telegram呢

dll中如何處理第一個參的

[此贴子已经被作者于2006-8-10 9:54:27编辑过]


[url=javascript:alert(1);] [div]fdgfdgfdg\" on\"[/div] [/url]
2006-08-10 09:49
jingzhao22visa
Rank: 1
等 级:新手上路
威 望:1
帖 子:343
专家分:0
注 册:2006-8-10
收藏
得分:0 
SharedTelList 控件
利用共享内存,在不同进程间交换数据报文。
文件:SharedTelList.Dll


命名空间:SharedTelList
对象名称:SharedTelList.SharedTelListCtrl
线程模型:自由线程或MultiThread Apartment

使用方法:
1、建立一个全局的SharedTelList.SharedTelListCtrl对象实例。
2、初始化该对象,BOOL InitSharedList(FileName,Name,MaxNum, MaxLen, bClear)

接收报文
3、定时或事件触发,检查该对象中的报文数量,当有报文时,用long GetFromHead(BYTE * Telegram)
接收报文,Telegram 是接收报文的内存缓冲区地址指针,该缓冲区长度必须大于等于最大报文长度,
返回实际报文的长度。

其它函数:
AddToHead(),将报文添加到队列头部

这个addintofile是我照着别人给的示例程序大部分抄过来的。

p = (byte*)&data; data 是Test——Struct 结构的一个实例。 我认为此处应该是指向该结构体示例的一个指针类型。telegram是该实例的一个数据成员
如下所示:
private unsafe struct Test_Struct
{
public int tel_id;
public fixed byte Telegram[2048];
public int test_data;
}

addtohead(ref byte Telegram,int Length int isOverWirte)
具体的我也只能看到这里。






2006-08-10 09:58
jingzhao22visa
Rank: 1
等 级:新手上路
威 望:1
帖 子:343
专家分:0
注 册:2006-8-10
收藏
得分:0 
经过我设置断点,参数ss确实已经传进去了。而且是server端所收到的那个string。
然后继续执行就是AddToHead函数了,这个我只能看见它执行,且没有报错。我就不知道该怎么办了。
后来觉得可能指针被垃圾回收掉了,想看看fixed 指针可不可以,但是fixed语句使用诸多限制,无法安上去。

感谢你的回答,请继续帮我看看吧。

2006-08-10 10:01
chenjin145
Rank: 1
等 级:禁止访问
帖 子:3922
专家分:0
注 册:2006-7-12
收藏
得分:0 

上面看了沒錯

AddToHead這個方法你有沒單獨用過 成功的
當時參數是如何傳遞的


[url=javascript:alert(1);] [div]fdgfdgfdg\" on\"[/div] [/url]
2006-08-10 10:11
jingzhao22visa
Rank: 1
等 级:新手上路
威 望:1
帖 子:343
专家分:0
注 册:2006-8-10
收藏
得分:0 
有的,dll是另一个人写的,他顺便也写了一个示例程序。包括增加报文和读报文。
我现在就是基本完全用的他的代码。那个示例程序完全没有错。
代码如下:




private void btnClose_Click(object sender, EventArgs e)
{
this.Close();
} //关闭窗口

private void btnInit_Click(object sender, EventArgs e)
{
string strV;
stlc = new SharedTelList.CSharedTelListCtrl();
if (stlc.InitSharedList("D:\\NetTelTest.dat", "SharedTel", 200, 4096, 1) != 0)
{
strV = string.Format("Initialize Telegram list success! Total telegram in list = {0}", stlc.Size);
System.Windows.Forms.MessageBox.Show(strV);
}
else
{
System.Windows.Forms.MessageBox.Show("Initialize Telegram list Fail!");
}
} //初始化文件,在这里我把文件清空


private unsafe void btnAdd1_Click(object sender, EventArgs e) //增加报文,也就是我的addintofile的函数了。
{
Test_Struct data;
byte *p ;
char[] bt;
//IntPtr ip;
//int i=0;
string strV = "Hello, this is a test";
bt = strV.ToCharArray();
//bt = Encoding.ASCII.GetBytes(strV);
int l=bt.Length;
data.tel_id = 99887;
data.test_data = 99999;
System.Runtime.InteropServices.Marshal.Copy(bt, 0, (IntPtr)data.Telegram, bt.Length);
///Buffer.BlockCopy(bt, 0, data.Telegram, 0, bt.Length);
//data.Telegram = strV;
//ip = new IntPtr((void *)data.Telegram);
//System.Runtime.InteropServices.Marshal.Copy(bt,0,ip,bt.Length);


p = (byte *)&data;
try
{
stlc.AddToHead(ref *p, sizeof(Test_Struct),1);
}
catch (Exception et)
{
MessageBox.Show(et.Message);
}
strV = string.Format("After add data. total {0} telegrams in list", stlc.Size);
MessageBox.Show(strV);
}

注明:我刚刚又试了一下,可以写入文件,但是全部都是乱码。比如,它这里可以写入Hello, this is a test"可以写入。我的写进去全是乱码,自然也无法读出来。 但是我不知道为什么会这样子。因为我几乎只是把它的传入的参数给改了而已。

private unsafe void btnReadData_Click(object sender, EventArgs e) //按照id99887来读写,弹出对话框。unkonwn id telegram
{
Test_Struct data;
byte[] buf = new byte[4086];
int telid;
int l;
string strV;
string strV1;
IntPtr p = new IntPtr((void *)&data);


try
{
l = stlc.GetFromTail(ref buf[0],0);
if (l == 0)
{
return;
}
telid = BitConverter.ToInt32(buf, 0);
if (telid == 99887)
{
//fixed ( void * pt = (void *)&data)
{

//p = (void*)&data;
System.Runtime.InteropServices.Marshal.Copy(buf, 0, p, l);

}
IntPtr p1 = new IntPtr((void*)data.Telegram);
strV1 = System.Runtime.InteropServices.Marshal.PtrToStringAuto(p1);
strV = string.Format("telid = {0}, test_data = {1}, telegram = |{2}|", data.tel_id, data.test_data, strV1);
MessageBox.Show(strV);
}
else
{
strV = string.Format("Unknow id telegram");
MessageBox.Show(strV);

}
stlc.DelFromTail(1);
}
catch (Exception et)
{
MessageBox.Show (et.Message);
}
}

private void Form1_Load(object sender, EventArgs e)
{

}
}

public unsafe struct Test_Struct
{
public int tel_id;
public fixed byte Telegram[2048];
public int test_data;
}

}

2006-08-10 10:26
chenjin145
Rank: 1
等 级:禁止访问
帖 子:3922
专家分:0
注 册:2006-7-12
收藏
得分:0 

差不多一模一樣,應該沒錯

你的數據裡面有中文之類或倆子節以上的子碼吧


bt = Encoding.ASCII.GetBytes(strV);
改為bt = Encoding.UTF8.GetBytes(strV); 看看


[url=javascript:alert(1);] [div]fdgfdgfdg\" on\"[/div] [/url]
2006-08-10 10:36
noshow
Rank: 2
等 级:新手上路
威 望:4
帖 子:1127
专家分:0
注 册:2006-4-21
收藏
得分:0 
以下是引用chenjin145在2006-8-10 10:36:30的发言:

差不多一模一樣,應該沒錯

你的數據裡面有中文之類或倆子節以上的子碼吧


bt = Encoding.ASCII.GetBytes(strV);
改為bt = Encoding.UTF8.GetBytes(strV); 看看

一般这个应该用Default的吧
我一般都这么用


感觉问题应该不是出在这里


说不定你写的是对的呢
你可以用UlTraEdit看看内码
和你写之前比较一下
只要内码一样就是没写错
只是显示的问题

[此贴子已经被作者于2006-8-10 10:42:46编辑过]


此号自封于2006年11月30日
2006-08-10 10:38
jingzhao22visa
Rank: 1
等 级:新手上路
威 望:1
帖 子:343
专家分:0
注 册:2006-8-10
收藏
得分:0 
哭了,我就说啊,我的代码几乎都没有变过啊。。。
我用的是string ss = Encoding.BigEndianUnicode.GetString(Receive_Buffer, 0, nBytesRec);
这个是可以发送字符和汉字的列。
他用的是:
string strV = ss;

bt = strV.ToCharArray(); //这个是要获得char[]数组的
data.tel_id = 99887;
data.test_data = 99999;
//fixed(byte * t=data.Telegram)
//{
//byte* tempt = t;
System.Runtime.InteropServices.Marshal.Copy(bt, 0, (IntPtr)data.Telegram, bt.Length); //byte[] 数组好像只能用这种形式来复制

p = (byte*)&data;

try
{
stlc.AddToHead(ref *p, sizeof(Test_Struct), 1);


反正我是不知道该怎么办了。。。。。
crying
昨天已经搞了一天了。。。

2006-08-10 10:59
chenjin145
Rank: 1
等 级:禁止访问
帖 子:3922
专家分:0
注 册:2006-7-12
收藏
得分:0 
bt = strV.ToCharArray(); //这个是要获得char[]数组的

這個改為bt = Encoding.UTF8.GetBytes(strV); 啊

[url=javascript:alert(1);] [div]fdgfdgfdg\" on\"[/div] [/url]
2006-08-10 11:02
快速回复:异步tcp通讯程序中读写文件的问题--第一次发帖请多关照
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.017303 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved