C++實現郵件群發的方法

来源:http://www.cnblogs.com/roucheng/archive/2016/06/22/cppmail.html
-Advertisement-
Play Games

這篇文章主要介紹了C++實現郵件群發的方法,較為詳細的分析了郵件發送的原理與C++相關實現技巧,非常具有實用價值,需要的朋友可以參考下 本文實例講述了C++實現郵件群發的方法。分享給大家供大家參考。具體如下:關於生成隨機QQ郵箱不精確的問題,在之後版本打算另寫一個採集器插件進行帳號採集,所以,這個軟 ...


這篇文章主要介紹了C++實現郵件群發的方法,較為詳細的分析了郵件發送的原理與C++相關實現技巧,非常具有實用價值,需要的朋友可以參考下

本文實例講述了C++實現郵件群發的方法。分享給大家供大家參考。具體如下:
關於生成隨機QQ郵箱不精確的問題,在之後版本打算另寫一個採集器插件進行帳號採集,所以,這個軟體只用來進行內容發送,郵箱進行隨機生成

如果你已經有採集來的QQ號,請複製到SendList.txt 替換內容即可
可以直接複製HTML代碼到郵件內容,保存即可。目前郵件內容最大設置為10000位元組,如果有增大的必要,歡迎提交留言。

這是我學習後VC編程中涉及到多線程,socket,及一些WINDOWS API的宗合應用
使用說明:

一、SMTP設置

1、SMTP設置中,收件箱地址:填寫郵箱地址為帳號測試郵箱,可以填寫你自己的郵箱作為接收測試。打星號為必填。郵箱帳號及密碼,是即將用於群發的帳號和密碼
2、群發發送時間間隔,預設為零,可以選擇填寫發送間隔時間,單位為秒,防止多次快速發送相同內容被停用。
3、勾選郵件標題後插入系統時間,可以在標題上加上系統時間
4、導入群發列表,勾選後,可以點擊群發,暫停,繼續。(群發列表為程式目錄中SendList.txt)如果你有郵箱採集軟體,可以把彩集的郵箱地址按照格式,一行一個,放入其中),沒有的話,可以點擊“收件箱”頁面生成隨機QQ郵箱

二、郵件內容

1、填寫郵件標題,郵件內容可以為純文本,也可以是HTML代碼,附件目前只支持TXT文本。
2、群發前,請測試郵件內容,是否完整。附件是否正常接收。

三、收件箱

1、收件箱中順序生成QQ郵箱,請不要超過6位數QQ號,位數過大,生成時間過長,容易造成假死。
2、群發前,先生成QQ郵箱列表。如果你有採集郵箱帳號,可以按格式放入SendList.txt 中

版本更新說明:

1、可增加多個附件。
2、修複標題插入日期造成程式崩潰的BUG。
3、增加發送間隔時間選項。
4、支持HTML代碼
5、增加干預碼

  1 #include "stdafx.h"
  2 #include <windows.h>
  3 #include <windowsx.h>
  4 #include "Resource.h"
  5 #include "TabDlg1.h"
  6 #include "winsock2.h"
  7 #define MAXSTRING 10000
  8 static int flag=0;     //標記是否群發
  9 TCHAR* pTitle = NULL;     //指向標題文件內容的指針
 10 HANDLE hThread=NULL;     //線程返回句柄
 11 long i=0;        //列表控制項“行”計數
 12 static long sendNum=1;    //發送郵件數量
 13 #pragma comment(lib,"WSOCK32.LIB")
 14 extern TCHAR tcRunPath[MAX_PATH];  //程式當前路徑目錄
 15 extern TCHAR shortPath[MAX_PATH];  //文件路徑,TAB2中的全局變數
 16 extern TCHAR titlePath[256];   //郵件標題文件路徑
 17 extern TCHAR mtPath[256];    //郵件內容文件路徑
 18 extern TCHAR sendListPath[MAX_PATH]; //發送列表文件路徑
 19 extern BOOL attach;     //是否添加了附件
 20 extern TCHAR file[MAXSTRING];   //附件部份代碼
 21 BOOL WINAPI TAB1_Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 22 {
 23  switch(uMsg)
 24  {
 25   HANDLE_MSG(hWnd, WM_INITDIALOG, TAB1_OnInitDialog);
 26   HANDLE_MSG(hWnd, WM_COMMAND, TAB1_OnCommand);
 27   HANDLE_MSG(hWnd,WM_CLOSE, TAB1_OnClose);
 28  }
 29  return FALSE;
 30 }
 31 BOOL TAB1_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
 32 {
 33  InitLVColumn(hwnd);
 34  InitComboBox(hwnd);
 35  return TRUE;
 36 }
 37 void TAB1_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
 38 { 
 39  IsChecked(hwnd);   //判斷勾選框是否被勾選
 40  IsRadioChecked(hwnd); //RADIO控制項是否被選擇
 41  switch(id)
 42  {
 43   case IDC_MAIL_TEST:
 44   {  
 45    if(IsDlgButtonChecked(hwnd,IDC_RADIO_QQ)!=BST_CHECKED && IsDlgButtonChecked(hwnd,IDC_RADIO_163)!=BST_CHECKED)
 46    {
 47     MessageBox(hwnd,TEXT("請選擇發QQ郵箱或163信箱"),"",MB_OK);
 48     return;
 49    }
 50    else
 51    {
 52     flag=0;
 53     hThread=CreateThread(NULL,0,ThreadFunc,hwnd,0,0);
 54    }
 55   }
 56   break;
 57   case IDC_BUTTON_START:
 58   {  
 59    if(IsDlgButtonChecked(hwnd,IDC_RADIO_QQ)!=BST_CHECKED && IsDlgButtonChecked(hwnd,IDC_RADIO_163)!=BST_CHECKED)
 60    {
 61     MessageBox(hwnd,TEXT("請選擇發QQ郵箱或163信箱"),"",MB_OK);
 62     return;
 63    }
 64    else
 65    {
 66     flag=1;
 67     hThread=CreateThread(NULL,0,ThreadFunc,hwnd,0,0);
 68    }
 69   }
 70   break;
 71   case IDC_BUTTON_PAUSE:
 72   {   
 73    if(NULL!=hThread)
 74    {
 75     SuspendThread(hThread); 
 76    }
 77    else
 78    {
 79     return;
 80    }
 81   }
 82   break;
 83   case IDC_BUTTON_RESUME:
 84   {   
 85    if(NULL!=hThread)
 86    {
 87     ResumeThread(hThread); 
 88    }
 89    else
 90    {
 91     return;
 92    }
 93   }
 94   break;
 95   default:
 96   break;
 97  }
 98 }
 99 void TAB1_OnClose(HWND hwnd)
100 {
101  EndDialog(hwnd, 0);
102 }
103 int InitLVColumn(HWND hwnd)    //列表初始化設置,視圖選為報表視圖
104 {
105  LVCOLUMN lvColumn;
106  MyLVColumn MyColumn[2] = {{TEXT("編號"), 0x30, LVCFMT_CENTER},{TEXT("郵箱帳號"), 0x99, LVCFMT_CENTER}};
107  lvColumn.mask = LVCF_TEXT|LVCF_FMT|LVCF_WIDTH|LVCF_SUBITEM;
108  DWORD dwStyle =ListView_GetExtendedListViewStyle(GetDlgItem(hwnd, IDC_LIST));   //得到列表當前拓展風格
109  dwStyle |= LVS_EX_FULLROWSELECT; //選中某行使整行高亮(只適用與report風格的listctrl)
110  dwStyle |= LVS_EX_GRIDLINES;  //網格線(只適用與report風格的listctrl)
111 // dwStyle |= LVS_EX_CHECKBOXES;  //item前生成checkbox控制項
112  ListView_SetExtendedListViewStyle(GetDlgItem(hwnd, IDC_LIST),dwStyle);     //設置列表擴展風格
113  for(int i = 0; i < 2; i++)
114  {
115   lvColumn.pszText = MyColumn[i].szColumnName;
116   lvColumn.cx = MyColumn[i].cx;
117   lvColumn.fmt = MyColumn[i].fmt;
118   SendDlgItemMessage(hwnd, IDC_LIST, LVM_INSERTCOLUMN, i, (LPARAM)&lvColumn);
119  }
120   
121  return 0;
122 }
123 int InitComboBox(HWND hwnd)//視窗控制項初始化設置
124 {
125  HWND hwndCombo=GetDlgItem(hwnd,IDC_COMBO_SLEEPTIME);
126  ComboBox_InsertString(hwndCombo,-1,TEXT("0"));
127  ComboBox_InsertString(hwndCombo,-1,TEXT("1"));
128  ComboBox_InsertString(hwndCombo,-1,TEXT("2"));
129  ComboBox_InsertString(hwndCombo,-1,TEXT("5"));
130  ComboBox_InsertString(hwndCombo,-1,TEXT("10"));
131  ComboBox_InsertString(hwndCombo,-1,TEXT("20"));
132  ComboBox_SetText(hwndCombo,TEXT("0"));
133  SetDlgItemText(hwnd,IDC_EDIT_MAILADD,TEXT("[email protected]"));
134  ComboBox_InsertString(GetDlgItem(hwnd,IDC_COMBO_SMTP),0,TEXT("smtp.qq.com"));
135  ComboBox_InsertString(GetDlgItem(hwnd,IDC_COMBO_SMTP),1,TEXT("smtp.163.com"));
136  ComboBox_SetText(GetDlgItem(hwnd,IDC_COMBO_SMTP),TEXT("smtp.qq.com"));
137  SetDlgItemText(hwnd,IDC_EDIT_MAILPORT,TEXT("25")); 
138  SetDlgItemText(hwnd,IDC_EDIT_USERNAME,TEXT(""));
139   
140  return 1;
141 }
142 int IsChecked(HWND hwnd)  //checkbox未選中的設置為只讀
143 {
144  if(IsDlgButtonChecked(hwnd,IDC_CHECK_QUNFA)!=BST_CHECKED)
145  {
146   EnableWindow(GetDlgItem(hwnd, IDC_BUTTON_START), false);
147   EnableWindow(GetDlgItem(hwnd, IDC_BUTTON_RESUME), false);
148   EnableWindow(GetDlgItem(hwnd, IDC_BUTTON_PAUSE), false);
149   return 0;
150  }
151  else
152  {
153   EnableWindow(GetDlgItem(hwnd, IDC_BUTTON_START), true);
154   EnableWindow(GetDlgItem(hwnd, IDC_BUTTON_RESUME), true);
155   EnableWindow(GetDlgItem(hwnd, IDC_BUTTON_PAUSE), true);
156   return 1;
157  }
158  return 0;
159 }
160 int IsRadioChecked(HWND hwnd) //RADIO控制項被選中,則設置相應的SMTP 地址
161 {
162  if(IsDlgButtonChecked(hwnd,IDC_RADIO_QQ)==BST_CHECKED)
163  {
164   ComboBox_SetText(GetDlgItem(hwnd,IDC_COMBO_SMTP),TEXT("smtp.qq.com"));
165   return 1;
166  }
167  if(IsDlgButtonChecked(hwnd,IDC_RADIO_163)==BST_CHECKED)
168  {
169   ComboBox_SetText(GetDlgItem(hwnd,IDC_COMBO_SMTP),TEXT("smtp.163.com"));
170   return 2;
171  }
172  return 0;
173 }
174 TCHAR* readText1(HWND hwnd)    //讀取文件--郵件發送內容
175 {
176  int nLen = 0;
177  FILE *pF = fopen(titlePath , "r"); //打開文件
178  fseek(pF, 0, SEEK_END);    //文件指針移到文件尾
179  nLen = ftell(pF);     //得到當前指針位置, 即是文件的長度
180  rewind(pF);       //文件指針恢復到文件頭位置
181  pTitle = (char*) malloc(sizeof(char)*nLen+1);//動態申請空間, 為保存字元串結尾標誌\0, 多申請一個字元的空間
182  if(!pTitle)
183  {
184   MessageBox(hwnd,TEXT("記憶體不夠!"),"錯誤",MB_ICONWARNING);
185   exit(0);
186  }
187  nLen = fread(pTitle, sizeof(char), nLen, pF);
188  pTitle[nLen] = '\0';   //添加字元串結尾標誌
189  if(IsDlgButtonChecked(hwnd,IDC_CHECK_TITLE)==BST_CHECKED) //是否勾選在郵件標題 加入系統當前時間
190  {
191   SYSTEMTIME stLocal;
192   GetLocalTime(&stLocal); //得到系統當前時間
193   TCHAR strTime[256];
194   ZeroMemory(strTime,sizeof(strTime)/sizeof(TCHAR));
195   wsprintf(strTime,"%04u-%02u-%02u %02u:%02u:%02u",stLocal.wYear,stLocal.wMonth,stLocal.wDay,stLocal.wHour,stLocal.wMinute,stLocal.wSecond);
196   strcat(pTitle,strTime); //在標題後加入系統時間
197  }
198  fclose(pF);     //關閉文件
199  TCHAR* pText = NULL;
200  pF = fopen(mtPath , "r"); //打開文件
201  fseek(pF, 0, SEEK_END); 
202  nLen = ftell(pF); 
203  rewind(pF); 
204  pText = (char*) malloc(sizeof(char)*nLen+1); //動態申請空間, 為保存字元串結尾標誌\0, 多申請一個字元的空間
205  if(!pText)
206  {
207   MessageBox(hwnd,TEXT("記憶體不夠!"),"錯誤",MB_ICONWARNING);
208   exit(0);
209  }
210  nLen = fread(pText, sizeof(char), nLen, pF);
211  pText[nLen] = '\0';   //添加字元串結尾標誌
212  fclose(pF);     //關閉文件
213  TCHAR chText[MAXSTRING];  
214  TCHAR* encText=base64_encode(pText,strlen(pText));  
215  strcpy(chText,encText);  //BASE64加密結果
216  free(encText);    //釋放指針
217  free(pText);     //釋放空間
218  return chText;
219 }
220 DWORD WINAPI ThreadFunc(LPVOID lpParam)//發郵件線程
221 {
222  HWND hwnd=(HWND)lpParam;
223  TCHAR userName[256];    //用戶帳號
224  TCHAR userPassWord[256];   //用戶密碼
225  GetDlgItemText(hwnd,IDC_EDIT_USERNAME,userName,sizeof(userName)/sizeof(TCHAR));
226  GetDlgItemText(hwnd,IDC_EDIT_USERPASSWORD,userPassWord,sizeof(userPassWord)/sizeof(TCHAR));
227  TCHAR *name=userName; 
228  int i = 0; 
229  int j = strlen(name); 
230  TCHAR *encName = base64_encode(name, j);    //給用戶名base64加密編碼  
231  ZeroMemory(userName,sizeof(userName)/sizeof(TCHAR)); 
232  wsprintf(userName,"%s\n", encName);      //在加編碼後加入回車符
233  TCHAR *passWord=userPassWord; 
234  int k = strlen(passWord); 
235  TCHAR *encPassWord = base64_encode(passWord, k);  //給用戶密碼base64加密編碼    
236  // int len = strlen(enc); 
237  // TCHAR *dec = base64_decode(enc, len);    //反編 
238  ZeroMemory(userPassWord,sizeof(userPassWord)/sizeof(TCHAR)); 
239  wsprintf(userPassWord,"%s\n", encPassWord);
240  /*ZeroMemory(userName,sizeof(userName)/sizeof(TCHAR)); 
241  wsprintf(userName,"\ndecoded : %s", dec);
242  MessageBox(hwnd,userName,"",MB_OK);*/     //反編譯用戶名,如果需要,可以把用戶名密碼反編後發到指定郵箱。
243  free(encName);           //釋放指針
244  free(encPassWord);
245  //free(dec); 
246  if(1==flag)            //全局標記,點擊群發還是測試,1為群發,0為測試
247  {
248    HANDLE wFile;
249    int szId;
250    TCHAR ch;
251    TCHAR szState[256];
252    strcpy(sendListPath,tcRunPath);
253    strcat(sendListPath,"\\SendList.txt");   //拼接全路徑及文件名
254    TCHAR *sFileName=sendListPath;
255    FILE *fp=fopen(sFileName,"r");
256    if(fp==NULL)
257    {
258     return FALSE;        //打開文件失敗,則返回,不讀取
259    }
260    fseek(fp, 0, SEEK_END);
261    int length = ftell(fp);      //length為0,則是空的
262    rewind(fp);         //把指針移迴文件頭部 還可以用 fseek(fp, 0, SEEK_SET);效果一樣
263    if(length==0)         //判斷文件如果為空,則關閉文件,返回,
264    {
265     fclose(fp);        //要關閉打開的文件,不然退出時,無法保存
266     return FALSE;
267    }
268    while(!feof(fp))
269    { 
270     fscanf(fp,"%s\r\n",szState);
271     SocketQ(hwnd,userName,userPassWord,szState);
272     TCHAR sTime[256];    
273     unsigned long iTime;
274     ComboBox_GetText(GetDlgItem(hwnd,IDC_COMBO_SLEEPTIME),sTime,sizeof(sTime)/sizeof(TCHAR));
275     iTime=atoi(sTime);
276     iTime=iTime*1000;
277     Sleep(iTime);
278    } 
279    fclose(fp);
280  }
281  else
282  {
283   Socket(hwnd,userName,userPassWord); 
284  }
285  CloseHandle(hThread); 
286  return 0;
287 }
288 void SocketQ(HWND hwnd,TCHAR userName[],TCHAR userPassWord[],TCHAR szState[])//傳入加密的用戶名跟密碼連接163
289 {
290    /*******************************************************************
291    使用Socket的程式在使用Socket之前必須調用WSAStartup函數。
292    該函數的第一個參數指明程式請求使用的Socket版本,
293    其中高位位元組指明副版本、低位位元組指明主版本;
294    操作系統利用第二個參數返回請求的Socket的版本信息。
295    當一個應用程式調用WSAStartup函數時,操作系統根據請求的Socket版本來搜索相應的Socket庫,
296    然後綁定找到的Socket庫到該應用程式中。
297    以後應用程式就可以調用所請求的Socket庫中的其它Socket函數了。
298    該函數執行成功後返回0。
299    *****************************************************************/
300   TCHAR* pText;
301   pText = readText1(hwnd);
302   int WSA_return;
303   WSADATA wsaData;   
304   WSA_return=WSAStartup(MAKEWORD(2,0),&wsaData);   //初始化Socket庫  
305   SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//創建SOCKET
306   hostent* host = NULL; 
307   SOCKADDR_IN sa;
308   sa.sin_family=AF_INET;         //設置電線連接伺服器端的埠
309   TCHAR cPort[100];
310   GetDlgItemText(hwnd,IDC_EDIT_MAILPORT,cPort,sizeof(cPort)/sizeof(TCHAR));
311   int iPort=atoi(cPort);
312   sa.sin_port = htons(iPort);   
313   //sa.sin_addr.S_un.S_addr = inet_addr("123.58.178.203");//可以寫死IP地址   
314    HOSTENT *host_entry;         //存放主機功能變數名稱,如smtp.qq.com
315    TCHAR host_name[256]="";
316    ZeroMemory(host_name,sizeof(host_name)/sizeof(TCHAR)); 
317    ComboBox_GetText(GetDlgItem(hwnd,IDC_COMBO_SMTP),host_name,sizeof(host_name)/sizeof(TCHAR));
318    TCHAR str_ipAdd[256];
319    if(WSA_return==0)
320    {
321    host_entry=gethostbyname(host_name);     // 要解析的功能變數名稱或主機名 
322    if(host_entry!=NULL)
323    {
324    wsprintf(str_ipAdd,"%d.%d.%d.%d",
325     (host_entry->h_addr_list[0][0]&0x00ff),
326     (host_entry->h_addr_list[0][1]&0x00ff),
327     (host_entry->h_addr_list[0][2]&0x00ff),
328     (host_entry->h_addr_list[0][3]&0x00ff));
329      
330    }
331    }
332   sa.sin_addr.S_un.S_addr = inet_addr(str_ipAdd);   //得到功能變數名稱IP地址
333   if(connect(sock,(SOCKADDR *)&sa,sizeof(sa))==SOCKET_ERROR)
334   {
335   ShowError();
336   return;
337   }
338   TCHAR buffer[256];          //對話過程  
339   ZeroMemory(buffer,sizeof(buffer)/sizeof(TCHAR));
340   int iRet=recv(sock,buffer,256,0);      //接收問候語  
341   if(SOCKET_ERROR==iRet)
342   {
343    ShowError();   
344    return;
345   }
346   TCHAR Hello[] = "HELO SMTP\r\n";      //註意不能忘了末尾的回車  
347   send(sock,Hello,lstrlen(Hello),0); 
348   ZeroMemory(buffer,sizeof(buffer)/sizeof(TCHAR)); 
349   iRet=recv(sock,buffer,256,0);
350   if(SOCKET_ERROR==iRet)
351   {
352    ShowError();   
353    return;
354   }
355   TCHAR Ehlo[] = "EHLO SMTP\r\n";  
356   send(sock,Ehlo,lstrlen(Ehlo),0); 
357   ZeroMemory(buffer,sizeof(buffer)/sizeof(TCHAR)); 
358   iRet=recv(sock,buffer,256,0);
359   if(SOCKET_ERROR==iRet)
360   {
361    ShowError();   
362    return;
363   }
364   TCHAR login[] = "AUTH LOGIN\r\n";      //登陸命令
365   send(sock,login,lstrlen(login),0); 
366   ZeroMemory(buffer,sizeof(buffer)/sizeof(TCHAR)); 
367   iRet=recv(sock,buffer,256,0);
368   if(SOCKET_ERROR==iRet)
369   {
370    ShowError();   
371    return;
372   }
373   if(IsDlgButtonChecked(hwnd,IDC_RADIO_QQ)==BST_CHECKED)
374   {
375    strcat(userName,"\r\n");
376    send(sock,userName,lstrlen(userName),0);   //發送加密的用戶名
377    ZeroMemory(buffer,sizeof(buffer)/sizeof(TCHAR)); 
378    iRet=recv(sock,buffer,256,0);
379    if(SOCKET_ERROR==iRet)
380    {
381     ShowError();   
382     return;
383    }
384    strcat(userPassWord,"\r\n");
385    send(sock,userPassWord,lstrlen(userPassWord),0); //發送加密的密碼
386    ZeroMemory(buffer,sizeof(buffer)/sizeof(TCHAR)); 
387    iRet=recv(sock,buffer,256,0);
388    if(SOCKET_ERROR==iRet)
389    {
390     ShowError();   
391     return;
392    }
393   }
394   if(IsDlgButtonChecked(hwnd,IDC_RADIO_163)==BST_CHECKED)
395   {
396    send(sock,userName,lstrlen(userName),0);   //發送加密的用戶名
397    ZeroMemory(buffer,sizeof(buffer)/sizeof(TCHAR)); 
398    iRet=recv(sock,buffer,256,0);
399    if(SOCKET_ERROR==iRet)
400    {
401     ShowError();   
402     return;
403    }
404    send(sock,userPassWord,lstrlen(userPassWord),	   

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 抽象類就是抽象的類,抽象是相對於具體而言的,一般而言,具體類有直接對應的對象,而抽象類沒有,它表達的是抽象概念 ... 但為什麼非要顯式將類設為抽象的呢?抽象類和介面某些地方很像,但其實根本不同,不過又互相聯繫,它們到底有著怎樣的關係呢? ...
  • 利用PHP,將資料庫中的文章數據生成單個的HTML文檔。首先,有利於搜索引擎的收錄。其次,避免資料庫中的欄位暴露在地址欄上,更安全。 給出代碼: <?php //引入資料庫配置文件 include( dirname(dirname(lxx_file))."\include\config.php" ) ...
  • 雙向鏈表實現 今天晚上用模板方法把雙向鏈表實現了下,由於有點小粗心,在 insert中手抖了下,把tail->prev 打成了 tail->next,由於錯誤是發生在drop函數執行時,讓我一直去調drop函數,調了半天還是一樣錯誤,最後我系統在vs中監視了下值的變化,終於看到是insert出錯了。 ...
  • 我們知道,(1)如果是整百的年份,能被400整除的,是閏年;(2)如果不是整百的年份,能被4整除的,也是閏年。每400年,有97個閏年。鑒於此,程式可以作以下設計: 第一步,判斷年份是否被400整除,能的話,就是閏年。比如1600、2000、2400年是閏年。 第二步,在第一步不成立的基礎上,判斷年 ...
  • 在jsp頁面中輸出完整的時間,格式為"年 月 日 時:分:秒" ...
  • 在導入文件的時候,Python只搜索當前腳本所在的目錄,載入(entry point)入口腳本運行目錄和sys.path中包含的路徑例如包的安裝地址。所以如果要在當前腳本引用其他文件,除了將文件放在和腳本同一目錄下,還有以下幾種方法, 1. 將文件所在位置添加到sys.path中 2. 在文件目錄下 ...
  • 這是ZK學習筆記的下篇, 主要希望可以分享一些 ZK 的應用以及其應用原理 我本人的學習告一段落, 不過還遺留了一些ZK相關的任務開發和性能測試的任務, 留待以後完成之後再通過其他文章來進行分享了 ZK應用場景: 1. 一個服務多台機器, 快速修改配置 2. 服務的消費者如何動態知道服務有多少個提供 ...
  • 因為 PHP 那“集百家之長”的蛋疼語法,加上社區氛圍不好,很多人對新版本,新特征並無興趣。本文將會介紹自 PHP5.2 起,直至 PHP5.6 中增加的新特征 本文目錄:PHP5.2 以前:autoload, PDO 和 MySQLi, 類型約束PHP5.2:JSON 支持PHP5.3:棄用的功能 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...