资源描述
Harbin Institute of Technology
C语言在测量与控制中的应用
实验报告
专 业: 控制科学与工程
班 级:
学 号:
姓 名:
设计时间: 2015年5月12日星期二
实验一 AD/DA数据采集实验
一、定时中断程序设计
实验的目的:
1. 掌握定时器/计数器8254的工作原理与编程。
2. 熟悉中断控制器8259A的工作原理与使用方法。
3. 掌握硬件中断程序设计的原理与编程方法。
实验条件:
PC机,WinXP操作系统,Turbo C 2.0
程序设计要求:
程序运行首先提示输入中断服务的时间间隔T和中断服务次数N,正确输入后,回车,则每间隔指定的时间T会在屏幕上显示一些字符,显示N次后,则不再显示,如果N=0,则会无限显示下去,直到在键盘上按下指定的按键,才停止显示。停止显示后,按任意键程序结束运行。
1. 时间间隔T为以毫秒为单位浮点数,可处理范围至少要0.001毫秒到5000毫秒。
2. 屏幕上的显示信息要有助于验证程序运行结果的正确。
3. 输入错误信息要有提示,并允许重新输入。
4. 编程时要尽量把具有独立功能的代码写成子程序。
5. 注意变量的命名要清晰,代码的注释要丰富。
6. 后面的三个实验均要在此程序基础上编程、添加代码,注意程序的结构。
设计思路
1. 如何实现任意时间间隔?(附程序流程图)
答:时间间隔的选择是根据用户需求进行相应设置。程序第一步用户输入时间间隔T(ms),在程序设计时,根据用户输入T(ms),并通过使用相应的语句对8254的通道0定时器设计数初值,然后将计数初值先写低8位,后写高8位的方式,初始化通道0。
代码实现为:
通过CalIPara()函数来计算计数初值的高低8位:
void CalIPara(double DTimeI,int *ILongCount,unsigned char *CL8, unsigned char *CH8) {
double TotalCounter=DTimeI*1193;
int Residue;
ILongCount[0]=TotalCounter/65536;
Residue=TotalCounter-65536*ILongCount[0];
CH8[0]=Residue>>8;
CL8[0]=Residue&0x0FF;
}
通过SetupTimerInterrupt()函数来对8254的通道0定时器的初始化:
void SetupTimerInterrupt(void) {
disable();
oldint8=getvect(0x08);
outportb(0x43,0x36);
if(LongCount==0) {
outportb(0x40,L8);
outportb(0x40,H8);
}
else {
outportb(0x40,0x00);
outportb(0x40,0x00);
}
setvect(0x08,myint8); enable();
}
这样,每隔T(ms)时间,8259A的中断请求信号引起中断服务的执行。时间间隔是由用户自己选择的,因此这样的设计能够实现任意时间间隔。程序流程图如下:
2. 如何设计显示信息便于验证定时的正确性?(文字表述及必要的代码)
答:为了验证定时的正确性,设计采用每次显示字符为中断次数的方法。首先,可以通过显示字符的频率来粗略验证定时的正确性,当然也可以数规定时间内的字符数计算中断时间间隔,与设定值比对。其次,中断次数可以验证有限次中断功能的正确性和无限次中断的手动请求停止功能的正确性。
具体实现可以通过中断时打印当前中断次数。具体代码如下:
printf("%d\t",CurrentInterruptNum);
3. 如何实现错误提示?(文字表述及必要的代码)
答:为了避免程序执行过程中发生错误,在用户每输入完一项数据后都要进行必要的正确性检验。如果输入不符合要求,则在必要的友好提示下,循环要求用户重新输入,直至输入正确数据。程序中,在InputInterruptPara函数中完成此项功能。具体代码如下所示。
printf("Please input time interval of interrupt events (milisecond): ");
do{
scanf("%le",&TimeInterval);
if(TimeInterval>5000 || TimeInterval<0.001) {
getchar();
printf("\n\tInvalid input! Time interval should be in the domain of [0.001,5000].");
printf("\n\tPlease input again: ");
}
else break;
}while(1);
printf("\nPlease input the times of interrupt: ");
do{
scanf("%d",&InterruptNum);
if(InterruptNum<0) {
getchar();
printf("\n\tInvalid input! Interrupt times should be no smaller than 0.");
printf("\n\tPlease input again: ");
}
4. 如何实现按键停止定时中断服务? (文字表述及必要的代码)
答:当用户输入中断次数为0时,中断将会一直执行,直至用户手动输入键盘上特定的按键以申请手动停止中断。具体实现上,通过kbhit()函数获取按键信号,通过bioskey(0)函数获得键值。具体代码如下所示。
(1) 在中断函数myint8中获得按键及键值
if(kbhit()) {
EndStroke=bioskey(0); }
(2) 在主函数中判断按键属性
/*Dead recycles depending on the value of user-input InterruptNum*/ if(InterruptNum!=0)
while(CurrentInterruptNum<InterruptNum);
else
/*Press C to stop*/
while(EndStroke!=11875);
5. 程序编写过程中遇到过的问题及解决办法。
答:出现的问题:在实现错误提示过程中,使用do-while函数进行循环判断时,错误输入数据后程序进行死循环,没有出现相应的输入提示。
解决办法:事实证明由于没有进行相关函数的缓冲,在do-while函数增加getchar()函数对输入进行缓冲,即解决这个问题。
程序运行结果截图(不同运行参数条件下)
1. 错误提示界面截图:
2. 中断时间:100ms,中断次数:50 截图如下:
3. 中断时间:200ms,中断次数: 0 (无限次中断),图示为按C键后结果,截图如下:
二、 数据处理与绘图程序设计
实验的目的:
1. 掌握数据文件的建立、存储和读取方法。
2. 掌握C语言绘图程序设计方法。
3. 掌握DosBox的使用方法。
实验条件:
PC机,WinXP操作系统,Turbo C 2.0,DosBox
程序设计要求:
程序运行前,配置数据文件(包括中断服务的时间间隔T,中断服务次数N,正弦曲线的振幅、周期,坐标系在屏幕上的位置,横(时间)纵(幅度)坐标显示范围及刻度等),运行后,首先,在屏幕上设定位置绘制坐标系,然后每间隔指定的时间生成设定的正弦曲线上的一个点,保存到指定数据文件并绘制在坐标系里,超过横坐标显示范围后,会滚动显示,显示N个点后,则曲线停止,如果N=0,则会无限显示下去,直到在键盘上按下指定的按键,才停止显示。停止显示后,按任意键程序结束运行。
1. 横坐标标注为时间,纵坐标标注为幅度。
2. 曲线动态显示
3. 配置文件如有错误要能提示,不会造成程序运行报系统错误。
4. 编程时要尽量把具有独立功能的代码写成子程序。
5. 注意变量的命名要清晰,代码的注释要丰富。
6. 后面的数据采集要在此程序基础上编程、添加代码,注意程序的结构。
设计思路
1. 如何实现配置文件参数的读取?(文字表述及必要的代码)
答:通过编写Setup.txt文件来实现,其中文件内容根据回车分行,依次为坐标系在屏幕上的位置、横(时间)纵(幅度)坐标显示范围及刻度、参考横线、网格、中断时间间隔及中断次数。具体说明如下图:
读取文件数据时,采用fscanf()函数读取,通过ReadSetupFromFile()函数实现,代码如下:
void ReadSetupFromFile(void) {
FILE *fp1;
fp1=fopen("Setup.txt","r"); fscanf(fp1,"%d,%d,%d,%d\n",&IWXMin,&IWXMax,&IWYMin,&IWYMax); fscanf(fp1,"%le,%le,%le,%le\n",&DXMin,&DXMax,&DYMin,&DYMax); fscanf(fp1,"%le,%le\n",&DXStep,&DYStep); fscanf(fp1,"%le\n",&DReferenceLine);
fscanf(fp1,"%d\n",&IGrid);
fclose(fp1);
}
2. 如何编写绘制坐标系的子程序? (文字表述及必要的代码)
答:首先,设计GetScreenX()函数、GetScreenY()函数以及GetInterval()函数来实现将用户配置的坐标系显示范围与刻度转化为实际屏幕上的点的位置的功能,然后根据坐标系在屏幕上的位置求出首尾点,通过画直线将坐标系画出来,即由 DTrail()函数来实现,代码如下:
int GetScreenX(double RealX,int WXMin,int WXMax,double XMin,double XMax) {
int WX=(WXMax-WXMin)/(XMax-XMin)*(RealX-XMin)+WXMin;
return WX;
}
int GetScreenY(double RealY,int WYMin,int WYMax,double YMin,double YMax) {
int WY=WYMax-(WYMax-WYMin)/(YMax-YMin)*(RealY-YMin);
return WY;
}
int GetInterval(double RealInterval,int WRegion,double Region) {
int Interval=WRegion/Region*RealInterval;
return Interval;
}
/*Draw the trail*/
void DTrail(int WXMin,int WXMax,int WYMin,int WYMax,double XMin,double XMax,double YMin,double YMax,double XStep,double YStep,double RefLine,int Grid){
char Label[10];
int WYRefLine;
int WDot;
int Dot;
int i;
/*Draw the frame*/ l
ine(WXMin,WYMin,WXMax,WYMin); /*top*/
line(WXMin,WYMin,WXMin,WYMax); /*left*/
line(WXMin,WYMax,WXMax,WYMax); /*Bottom*/
line(WXMax,WYMin,WXMax,WYMax);/*right*/
/*Draw reference line*/
WYRefLine=GetScreenY(RefLine,WYMin,WYMax,YMin,YMax); line(WXMin,WYRefLine,WXMax,WYRefLine);
gcvt(RefLine,5,Label);
outtextxy(WXMax+1,WYRefLine-2,Label);
/*Draw X Step*/
i=0;
while(1) {
Dot=XMin+i*XStep; WDot=GetScreenX(Dot,WXMin,WXMax,XMin,XMax); if(WDot>WXMax) {
break;
}
if(Grid==1) {
line(WDot,WYMin,WDot,WYMax);
}
else{
line(WDot,WYMax,WDot,WYMax-5);
}
gcvt(Dot,5,Label);
outtextxy(WDot-5,WYMax+8,Label);
i++;
}
/*Draw y Step*/
i=0;
while(1) {
Dot=YMin+i*YStep; WDot=GetScreenY(Dot,WYMin,WYMax,YMin,YMax); if(WDot<WYMin) {
break;
}
if(Grid==1) {
line(WXMin,WDot,WXMax,WDot);
}
else{
line(WXMin,WDot,WXMin+5,WDot);
}
gcvt(Dot,5,Label);
if(Dot<0) {
outtextxy(WXMin-30,WDot-2,Label);
}
else {
outtextxy(WXMin-20,WDot-2,Label);
}
i++;
}
}
3. 如何保存数据文件,数据文件的格式?(文字表述及必要的代码)
答:读取文件数据后先提示输入保存数据文件名称,将模拟得到的数据保存在该文件中,保存数据时,采用文件写入功能,加制表符分割,将数据写入。格式如图所示:
代码如下:
fprintf(fp,"%d\t%d\t%le\t%le\n",Index,IData,RealTime,DData);
4. 如何将生成的正弦数据动态显示成曲线?(文字表述及必要的代码)
答:每次的中断过程中,根据中断时间和当前中断次数计算出当前时间,代入到模拟的数据采集正弦函数中,则可求得当前点的纵坐标,再根据已有的前一点数据,连接两点得到一较短线段,当时中断次数较大时,就能够打正弦曲线绘制出来,由于中断过程是不断进行的,因此在坐标系上看实现了动态效果。
同时,实际中使用中可能会出现幅值超过坐标显示范围的部分,因此对这部分也需要进行一定的处理,因此,考虑到超出部分是由于坐标系的Y轴坐标不够大,这可以对Setup.txt文件中进行相应的修改即可,因此超出坐标轴的部分不进行显示。代码如下:
/*Draw X Step*/
i=0;
while(1) {
Dot=XMin+i*XStep;
WDot=GetScreenX(Dot,WXMin,WXMax,XMin,XMax);
if(WDot>WXMax) {
break;
}
if(Grid==1) {
line(WDot,WYMin,WDot,WYMax);
}
else {
line(WDot,WYMax,WDot,WYMax-5);
}
gcvt(Dot,5,Label);
outtextxy(WDot-5,WYMax+8,Label);
i++;
}
/*Draw y Step*/
i=0;
while(1) {
Dot=YMin+i*YStep;
WDot=GetScreenY(Dot,WYMin,WYMax,YMin,YMax);
if(WDot<WYMin) {
break;
}
if(Grid==1) {
line(WXMin,WDot,WXMax,WDot);
}
else {
line(WXMin,WDot,WXMin+5,WDot);
}
gcvt(Dot,5,Label);
if(Dot<0) {
outtextxy(WXMin-30,WDot-2,Label);
}
else {
outtextxy(WXMin-20,WDot-2,Label);
}
i++;
}
5. 如何实现滚动? (文字表述及必要的代码)
答:由于连续实时显示,实际绘图可能超过坐标轴显示范围。设计要求指出,当在图像超出x轴显示范围时,将在新的一张坐标轴中显示。所以,绘制图像时,当判断到当前点的横坐标超出x轴范围时,刷新坐标系,通过计算当前点与前一点连线与y轴的交点,在新的坐标系中仅显示交点到当前点部分线段。同时,横坐标刻度也相应累加。以此实现动态效果。
具体代码如下:
if(RealTime>DXMax) {
XRegion=DXMax-DXMin;
DXMin=DXMax;
DXMax=DXMin+XRegion;
cleardevice(); DrawCoordinate(IWXMin,IWXMax,IWYMin,IWYMax,DXMin,DXMax,DYMin,DYMax,DXStep,DYStep,DReferenceLine,IGrid);
LastWDotX=IWXMin-1;
}
if(RealTime<=DXMax) {
WDotX=GetScreenX(RealTime,IWXMin,IWXMax,DXMin,DXMax); WDotY=GetScreenY(DData,IWYMin,IWYMax,DYMin,DYMax); if(LastWDotX<IWXMin) {
line(WDotX,WDotY,WDotX,WDotY);
}
else {
line(WDotX,WDotY,LastWDotX,LastWDotY);
}
LastWDotX=WDotX;
LastWDotY=WDotY;
}
程序运行结果截图(不同运行条件下)
中断时间是100ms,幅值为50,程序运行如下:
中断时间是400ms,幅值为50,程序运行如下:
三、 AD/DA数据采集与模拟量输出实验
实验的目的:
1. 熟悉AD/DA卡的工作原理
2. 掌握AD/DA卡的安装、配置及编程方法。
3. 了解实时数据采集和模拟量输出的常用方案。
实验条件:
1. 具有ISA总线插槽和USB接口的PC系列微型计算机,操作系统使用DOS或Windows98, 装有Turbo C 2.0,DosBox。
2. 超低频信号发生器。
3. 超低频示波器。
4. HY1232模入/模出接口板。
程序设计要求:
程序运行前,配置数据文件,运行后,首先,在屏幕上设定位置绘制坐标系,然后每间隔指定的时间通过A/D采集信号发生器的输出信号,保存到指定数据文件、绘制在坐标系里、并通过D/A输出,
1. 能通过配置文件来改变程序的运行模式,不必修改代码即可让程序在启动时或者工作于实验二方式或者工作于实验三方式。
2. A/D采集过程得到的数字量及解码后得到模拟量均要保存到数据文件中
设计思路
1. A/D转换代码的实现?(文字表述及必要的代码)
答:进行从端口读入AD12位AD值,使用位运算组合后,乘上对应的系数,就得到了AD采样值。
代码如下:
outportb(0x280,0x00);
while((inportb(0x285)&0x80)==0) {
;
}
IData=inportb(0x281)|((inportb(0x282)&0x0f)<<8);
DData=5-(4095-IData)*10./4096;
2. 解码的原理和实现? (文字表述及必要的代码)
答:12位AD对应-5V到+5V之间的电压变化,产生212=4096个量,所以该12位AD的分辨率为:10/4096=0.00244140625V。代码为:
outportb(0x280,0x00);
while((inportb(0x285)&0x80)==0) {
;
}
IData=inportb(0x281)|((inportb(0x282)&0x0f)<<8);
DData=5-(4095-IData)*10./4096;
DData就是实际的电压值。
3. D/A转换的数字量与A/D转换的数字量如何变换?D/A的实现? (文字表述及必要的代码)
答:D/A转换时,把12位A/D转换的结果通过位运算分解为两个8位数字量,通过端口控制D/A输出。程序如下:
if(IData<4095) {
IDAData=IData+1;
}
else {
IDAData=IData;
}
outportb(0x283,IDAData&0x0ff);
outportb(0x284,(IDAData>>8)&0x0f);
4. 如何实现实验二和实验三的切换? (文字表述及必要的代码)
答:通过在设置一个变量ADDA,当ADDA==0时,进行实验二, ADDA==1时,进行实验三。从而可以实现实验二和实验三的切换。在Process()函数中插入代码:
if(RealTimeShow==1){
outportb(0x280,0x00);
do{
;
}while(!(inportb(0x285)&0x80));
IData=inportb(0x281)|((inportb(0x282)&0x0f)<<8); /*A/D*/
DData=5-(4095-IData)*10.0/(pow(2,12));
ADDA=(DealedData-(-5))*pow(2,12)/10; /*D/A*/
outportb(0x283,(ADDA&0x00ff));
outportb(0x284,((ADDA>>8)&0x0f));
}
else if(RealTimeShow==0){
IData=Index%10;
DData=50*sin(Index);
}
5. 程序运行结果截图
实验二 串口测试界面实验
实验目的:
1、 掌握C++Builder软件的使用方法;
2、 学习C++类的使用,以及多线程类的使用;
3、 了解串口的工作原理以及基本通信参数配置。
实验条件:
PC机,winXP操作系统,C++Builder 6.0
程序设计要求
使用C++Builder画出基本的串口测试界面,通过界面上的控制接口实现打开、关闭串口;串口通信参数:波特率、奇偶校验位、停止位、位数的配置;发送数据的进制选择;实现串口之间的通信。
1、 串口不可以被重复打开,错误的时候要实现错误信息的提示;
2、 所有发送接收数据的信息要在界面上得以显示;
3、 编程时注意C++类的封装,提供合理的控制接口;
4、 注意变量的命名要清晰,代码的注释要丰富。
设计思路
1、 如何实现多线程类的继承和使用?
C++Builder提供了一个TThread的多线程虚拟类,在C++Builder中选择新建一个TThread类就自动实现了多线程类的继承,TThread类是一个虚拟类,它的多线程执行Execute()函数是一个空函数,所以TThread类本身无法创建一个具体的对象;在继承类中,我们对Execute()函数进行重载,在函数体中加入执行代码,这样就可以实现对新建继承类的对象创建。
使用过程:
A、创建一个多线程类对象:
ThreadCom = new TThreadCom(true);
B、对该多线程对象进行设置并启动运行:
ThreadCom->FreeOnTerminate=true;
ThreadCom->Resume();
C、关闭串口时,终止对象:
ThreadCom->Terminate();
2、如何实现对于串口的打开关闭以及通信参数配置?
在程序中,我们使用创建文件的方式获得串口的句柄,进而打开一个串口。同样也可以使用关闭文件的方式实现对于串口的解除使用。
hCom=CreateFile(StrComName.c_str(), //串口名
GENERIC_READ|GENERIC_WRITE, //打开方式
NULL, //独占访问
NULL, //无安全描述符指针
OPEN_EXISTING, //标识该资源必须存在
0,// FILE_ATTRIBUTE_NORMAL,
NULL);
CloseHandle(hCom);
而对于串口通信参数的配置,则是借助GetCommState()函数获取串口的当前配置,然后对相关参数进行修改后,再使用SetCommState()函数进行参数设置,从而实现对于串口参数的配置。
DCB dcb;
GetCommState(hCom,&dcb);
dcb.BaudRate=IntBaudRate; // current baud rate
dcb.Parity =IntParity; // 0-4=no,odd,even,mark,space
dcb.StopBits=IntStopBits; // 0,1,2 = 1, 1.5, 2
dcb.ByteSize=8; // number of bits/byte, 4-8
SetCommState(hCom,&dcb);
3、如何实现对于数据的发送和接收以及相关的定时参数设置?
从前面可以知道,对于串口设备,我们使用打开和关闭文件的方式对其进行操作,所以使用串口进行数据读写的时候,也是使用对于文件读写的方式进行。
发送数据:
WriteFile(hCom, //文件句柄
mSendData, //待发送数据的缓存区首地址
mSendDataLength, //本次要发送的数据长度
&dwBytesWrite, //本次成功发送的数据长度
NULL);
接收数据:接收数据是一个被动的过程,程序要一直检查串口有没有数据要接收,这也是我们使用多线程的原因,我们使用一个独立的线程一直对串口实行读操作,这样一旦有发送来的数据就可以直接接收。
//独立新线程的工作函数体
void __fastcall TThreadCom::Execute(void)
{
int MAXDATASIZE=10;
while(!Terminated) //当进程存在的时候,一直执行
{
ReadFile(hCom, //文件句柄
ReceivedData, //存放数据的缓存区地址
MAXDATASIZE, //本次要接收的数据长度
&dwBytesRead, //本次成功接收的数据长度
NULL);
if(dwBytesRead>0)
{
//当接收到数据的时候,把数据长度和存储地址告诉界面类,实现数据显示
Tcomtest->GETData(dwBytesRead,ReceivedData);
}
}
CloseCom(); //进程终止的时候,自动关闭串口
}
从前面数据发送和接收的函数可以看出,成功收发的数据长度和要收发的数据长度是两个独立的变量,它们经常不同。这是因为在我们收发的过程中,特别是接收的时候,我们采用查询的方式一直对串口进行接收,在大多数情况下串口接收缓存区都是空的,也就是说读操作是不能实现的,这就要求我们在读写进行规定时间内自动结束。这里我们使用SetCommTimeouts()函数对读写操作进行定时设置。
//超时设置
COMMTIMEOUTS commtimeout;
memset(&commtimeout,0,sizeof(int));
commtimeout.ReadTotalTimeoutMultiplier=5;//读总超时系数
commtimeout.ReadTotalTimeoutConstant=50;//读总超时常数
commtimeout.ReadIntervalTimeout=100;//读间隔超时
commtimeout.WriteTotalTimeoutMultiplier=5;//写总超时系数
commtimeout.WriteTotalTimeoutConstant=100;//写总超时常数
SetCommTimeouts(hCom,&commtimeout);
4、错误提示和进制选择
一个友好的界面会在用户错误操作的时候提示错误信息,本程序中主要通过两种方式对错误信息进行提示,一种是通过返回值等信息判断出当前的状态,并把状态信息显示在界面上。另外一种方式就是,当错误发生时,提示信息会以单钮对话框的形式进行显示。
if(status==true)
Memo1->Lines->Add("打开"+StrComName+" 成功");
else
Memo1->Lines->Add("打开"+StrComName+" 失败");
ShowMessage(StrComName+"正处于打开状态,不能再次打开!");
对于进制,存在两种情况,16进制和10进制,当16进制的时候,程序会在数字的前面加上“0x”,然后进行字符串到整型数据转换。
for(int i=0;i<DataNum;i++)
{
StrMid=StrData.SubString(3*i+1,2);
if(Hexadecimal->Checked==true)
{
StrMid="0x"+StrMid;
}
SendDataBUF[i]=StrToInt(StrMid);
实验结果截图:
两个串口测试界面相互通信的测试结果:
实验三 服务器与客户端测试界面
实验目的:
1、掌握C++Builder使用方法;
2、学习了解服务器和客户端控件的使用方法;
3、了解网络通信的原理和过程。
实验条件:
PC机,winXP操作系统,C++Builder 6.0
程序设计要求
设计一个服务器和客户端界面。对于客户端,可以通过界面输入的IP地址和串口号向服务器发起连接请求;对于服务器可以接受多个客户端的连接。可以实现每个客户端和服务器之间的网络通信。
1、服务器打开之后,获取自身的IP地址,然后进行请求通信;
2、服务器和客户端的所有状态和通信情况都在界面窗口上进行显示;
3、服务器在界面上显示所连接的所有客户端情况,并可以实现单独数据发送和断开连接;
4、服务器和客户端都可以实现主动断开连接,其中,服务器可以实现广播消息和断开所有连接的功能。
设计思路
1、如何获取本地的IP地址?
获取本机的IP地址从程序上可以分为3个过程。首先是用GetComputerName()获取本机名称;然后使用客户端类的内置函数LookupName()得到IP值;最后将IP值转化为AnsiString类型供调用使用。
//获取本机IP地址
//获取计算机名
AnsiString TModuleSSocket::GetMyComputerName()
{
CHAR CName[255];
DWORD L=255;
GetComputerName(CName,&L);
AnsiString StrMid=CName;
return StrMid;
}
in_addr TModuleSSocket::GetLocalIn_Addr()
{
AnsiString StrMyComputerName=GetMyComputerName();
in_addr a=SSocket->Socket->LookupName(StrMyComputerName);//获取指定计算机名IP
return a;
}
AnsiString TModuleSSocket::GetLocalIP()
{
in_addr a=GetLocalIn_Addr();//获取指定计算机名的IP
AnsiString StrIP=IntToStr(a.S_un.S_un_b.s_b1)+"."+
IntToStr(a.S_un.S_un_b.s_b2)+"."+
IntToStr(a.S_un.S_un_b
展开阅读全文