天天看點

c++序列槽操作

0. 前言

  做序列槽方面的程式,使用CreateFile打開序列槽通信端口。在對序列槽操作之前,需要首先打開序列槽。使用C++進行序列槽程式設計,如果采用VS開發,則可以直接借助于序列槽通信控件來操作,其次,直接調用Windows的底層API函數來控制序列槽通信。

  在Window 32bit 的作業系統上, 将序列槽(通信裝置)作為檔案來處理,是以序列槽的打開、關閉、讀寫所使用的API函數與檔案操作一樣。是以打開序列槽使用CreateFile函數,讀寫序列槽使用ReadFile、WriteFile,函數。關閉序列槽使用CloseHandle函數。

1. 檢視通信序列槽裝置,可以在裝置管理器中檢視;

2.

-------------------------------

1. CreateFile

  這個函數的功能是建立或者打開一個檔案或者I/O裝置,通常使用的I/O形式有檔案、檔案流、目錄、實體磁盤、卷、終端流等。如執行成功,則傳回檔案句柄。 INVALID_HANDLE_VALUE 表示出錯,會設定 GetLastError 。 

  函數的聲明定義:

  HANDLE WINAPI CreateFile(
  _In_      LPCTSTR lpFileName,              
  _In_      DWORD dwDesiredAccess,
  _In_      DWORD dwShareMode,
  _In_opt_  LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  _In_      DWORD dwCreationDisposition,
  _In_      DWORD dwFlagsAndAttributes,
  _In_opt_  HANDLE hTemplateFile
);      

參數清單:

c++序列槽操作

 部分參數Tips:

  1. lpFileName:指定要打開的序列槽邏輯名,用字元串來表示。如COM1, COM2,分别表示序列槽1,和序列槽2.

  如果要确定工控機上有那些序列槽,可以使用裝置管理器檢視。如下圖:

  

c++序列槽操作

  檢視方式如下圖:我的電腦,右鍵, 開發“裝置管理器”即可。

  

c++序列槽操作

   2. dwDesiredAccess:端口屬性的通路類型,

  3.  dwShareMode:指定端口的共享屬性。

  該參數是由那些應用程式共享的檔案提供。對于序列槽來說,是不能共享的,是以,必須設定為0,這是通信裝置與檔案的特殊差别。

  如果目前的應用程式調用CreateFile打開一個序列槽,另外一個程式如果已經打開了該序列槽,此時CreateFile會傳回一個錯誤代碼。

  然而,同一個應用程式的多個線程是可以共享CreateFile傳回的端口句柄。并且根據安全屬性設定,該句柄可以打開端口的應用程式的子程式來繼承。

  4. lpSecurityAttributes:安全屬性,一般該參數為NULL,即該端口被設定為預設的安全屬性。預設安全屬性下,端口的句柄是不能繼承的。

  5. dwCreationDisposition:指定此端口正在被其他程式占用采取的動作,因為序列槽總是存在的,是以必須設定為OPEN_EXISTing, 該标志高速Windows不要建立新的端口。而是打開一個已經存在的端口。

,  6. dwFlagsAndSttributes:描述了端口的各種屬性,對于檔案來說有很多屬性,但是對于序列槽來說,唯一的意義是FILE_FLAG _OVERLAPPED 屬性,當設定該屬性時,端口IO可以在背景進行,稱為異步IO重疊結構。

  7. hTemplateFile: 指定模闆的檔案句柄,對于序列槽來說,此參數必須設定為0;

  

c++序列槽操作

關閉序列槽

  關閉序列槽,使用CloseHandle,函數聲明為:

  

c++序列槽操作

  函數很簡單,參數是使用CreateFile打開的端口句柄。調用這個函數可以實作序列槽關閉。

   示例如下:

  

c++序列槽操作

2. ReadFile

從檔案指針指向的位置(裝置檔案,通信)開始将資料讀出到一個檔案中, 且支援同步和異步操作,如果檔案打開方式沒有指明FILE_FLAG_OVERLAPPED的話,當程式調用成功時,它将實際讀出檔案的位元組數儲存到lpNumberOfBytesRead指明的位址空間中。FILE_FLAG_OVERLAPPED 允許對檔案進行重疊操作。 

  函數聲明定義:

 BOOL WINAPI ReadFile(
  __in          HANDLE hFile,                   // 檔案句柄
  __out         LPVOID lpBuffer,                // 接收資料用的 buffer
  __in          DWORD nNumberOfBytesToRead,     // 要讀取的位元組數
  __out         LPDWORD lpNumberOfBytesRead,    // 實際讀取到的位元組數
  __in          LPOVERLAPPED lpOverlapped       // OVERLAPPED 結構,一般設定為 NULL 
);      

代碼示例:、

1 BOOL Read(char *filePath)
 2 {
 3     HANDLE pFile;
 4     DWORD fileSize;
 5     char *buffer,*tmpBuf;
 6     DWORD dwBytesRead,dwBytesToRead,tmpLen;
 7 
 8     pFile = CreateFile(filePath,GENERIC_READ,          
 9         FILE_SHARE_READ,
10         NULL,               
11         OPEN_EXISTING,        //打開已存在的檔案 
12         FILE_ATTRIBUTE_NORMAL, 
13         NULL);
14   // 建立裝置檔案,傳回檔案的位置
15     if ( pFile == INVALID_HANDLE_VALUE)
16     {
17         printf("open file error!\n");
18         CloseHandle(pFile);
19         return FALSE;
20     }
21   
22     fileSize = GetFileSize(pFile,NULL);          //得到檔案的大小
23 
24     buffer = (char *) malloc(fileSize);
25     ZeroMemory(buffer,fileSize);
26     dwBytesToRead = fileSize;
27     dwBytesRead = 0;
28     tmpBuf = buffer;
29 
30     do{                                       //循環讀檔案,確定讀出完整的檔案    
31 
32         ReadFile(pFile,tmpBuf,dwBytesToRead,&dwBytesRead,NULL);
33 
34         if (dwBytesRead == 0)
35             break;
36 
37         dwBytesToRead -= dwBytesRead;
38         tmpBuf += dwBytesRead;
39 
40         } while (dwBytesToRead > 0);
41 
42         //  TODO 處理讀到的資料 buffer
43 
44     free(buffer);
45     CloseHandle(pFile);
46 
47     return TRUE;
48 }      

3. WriteFile

  将資料寫入一個檔案(裝置檔案,通信)。該函數比fwrite函數要靈活的多。也可将這個函數應用于對通信裝置、管道、套接字以及郵槽的處理。傳回時,TRUE(非零)表示成功,否則傳回零。會設定GetLastError。 

函數聲明定義:

BOOL WINAPI WriteFile(
  __in          HANDLE hFile,                   // 檔案句柄
  __in          LPCVOID lpBuffer,               // 要寫入的資料
  __in          DWORD nNumberOfBytesToWrite,    // 要寫入的位元組數
  __out         LPDWORD lpNumberOfBytesWritten, // 實際寫入的位元組數
  __in          LPOVERLAPPED lpOverlapped       // OVERLAPPED 結構,一般設定為 NULL
);      

示例代碼:

1 BOOL Write(char *buffer, DWORD contentLen)
 2 {
 3     HANDLE pFile;
 4     char *tmpBuf;
 5     DWORD dwBytesWrite,dwBytesToWrite;
 6 
 7     pFile = CreateFile(filePath,GENERIC_WRITE,          
 8         0,
 9         NULL,               
10         CREATE_ALWAYS,        //總是建立檔案
11         FILE_ATTRIBUTE_NORMAL, 
12         NULL);
13 
14     if ( pFile == INVALID_HANDLE_VALUE)
15     {
16         printf("create file error!\n");
17         CloseHandle(pFile);
18         return FALSE;
19     }
20 
21     dwBytesToWrite = contentLen;
22     dwBytesWrite = 0;
23 
24     tmpBuf = buffer;
25 
26     do{                                       //循環寫檔案,確定完整的檔案被寫入  
27 
28         WriteFile(pFile,tmpBuf,dwBytesToWrite,&dwBytesWrite,NULL);
29 
30         dwBytesToWrite -= dwBytesWrite;
31         tmpBuf += dwBytesWrite;
32 
33         } while (dwBytesToWrite > 0);
34 
35     CloseHandle(pFile);
36 
37     return TRUE;
38 }      

繼續閱讀