C++利用SOCKET傳送文件

C++利用SOCKET傳送文件

/*server.h*/

#pragma comment(lib, "WS2_32")

#include <WinSock2.h>
#include <iostream>
//#include <stdio.h>
#include <assert.h>

#ifndef COMMONDEF_H
#define COMMONDEF_H

#define MAX_PACKET_SIZE?? 10240??? // 數據包的最大長度,單位是sizeof(char)
#define MAXFILEDIRLENGTH 256???? // 存放文件路徑的最大長度
#define PORT???? 4096??? // 端口號
#define SERVER_IP??? "127.0.0.1" // server端的IP地址

// 各種消息的宏定義
#define INVALID_MSG????? -1?? // 無效的消息標識
#define MSG_FILENAME???? 1?? // 文件的名稱
#define MSG_FILELENGTH???? 2?? // 傳送文件的長度
#define MSG_CLIENT_READY??? 3?? // 客戶端準備接收文件
#define MSG_FILE????? 4?? // 傳送文件
#define MSG_SENDFILESUCCESS??? 5?? // 傳送文件成功
#define MSG_OPENFILE_ERROR??? 10?? // 打開文件失敗,可能是文件路徑錯誤找不到文件等原因
#define MSG_FILEALREADYEXIT_ERROR 11?? // 要保存的文件已經存在了

class CCSDef
{
public:
#pragma pack(1)????? // 使結構體的數據按照1字節來對齊,省空間

// 消息頭
struct TMSG_HEADER
{
?? char??? cMsgID;??? // 消息標識

?? TMSG_HEADER(char MsgID = INVALID_MSG)
??? : cMsgID(MsgID)
?? {
?? }
};

// 請求傳送的文件名
// 客戶端傳給服務器端的是全路徑名稱
// 服務器傳回給客戶端的是文件名
struct TMSG_FILENAME : public TMSG_HEADER
{
?? char szFileName[256];?? // 保存文件名的字符數組

?? TMSG_FILENAME()
??? : TMSG_HEADER(MSG_FILENAME)
?? {
?? }
};

// 傳送文件長度
struct TMSG_FILELENGTH : public TMSG_HEADER
{
?? long lLength;

?? TMSG_FILELENGTH(long length)
??? : TMSG_HEADER(MSG_FILELENGTH), lLength(length)
?? {

?? }
};

// Client端已經準備好了,要求Server端開始傳送文件
struct TMSG_CLIENT_READY : public TMSG_HEADER
{
?? TMSG_CLIENT_READY()
??? : TMSG_HEADER(MSG_CLIENT_READY)
?? {
?? }
};

// 傳送文件
struct TMSG_FILE : public TMSG_HEADER
{
?? union???? // 采用union保證了數據包的大小不大于MAX_PACKET_SIZE * sizeof(char)
?? {
??? char szBuff[MAX_PACKET_SIZE];
??? struct
??? {
???? int nStart;
???? int nSize;
???? char szBuff[MAX_PACKET_SIZE - 2 * sizeof(int)];
??? }tFile;
?? };

?? TMSG_FILE()
??? : TMSG_HEADER(MSG_FILE)
?? {

?? }
};

// 傳送文件成功
struct TMSG_SENDFILESUCCESS : public TMSG_HEADER
{
?? TMSG_SENDFILESUCCESS()
??? : TMSG_HEADER(MSG_SENDFILESUCCESS)
?? {
?? }
};

// 傳送出錯信息,包括:
// MSG_OPENFILE_ERROR:打開文件失敗
// MSG_FILEALREADYEXIT_ERROR:要保存的文件已經存在了
struct TMSG_ERROR_MSG : public TMSG_HEADER
{
?? TMSG_ERROR_MSG(char cErrorMsg)
??? : TMSG_HEADER(cErrorMsg)
?? {
?? }
};

#pragma pack()
};

#endif

/*server.cpp*/

#include "server.h"

char g_szNewFileName[MAXFILEDIRLENGTH];
char g_szBuff[MAX_PACKET_SIZE + 1];
long g_lLength;
char* g_pBuff = NULL;

// 初始化socket庫
bool InitSocket();
// 關閉socket庫
bool CloseSocket();
// 解析消息進行相應的處理
bool ProcessMsg(SOCKET sClient);
// 監聽Client的消息
void ListenToClient();
// 打開文件
bool OpenFile(CCSDef::TMSG_HEADER* pMsgHeader, SOCKET sClient);
// 傳送文件
bool SendFile(SOCKET sClient);
// 讀取文件進入緩沖區
bool ReadFile(SOCKET sClient);

int main()
{
InitSocket();
ListenToClient();
CloseSocket();

return 0;
}

void ListenToClient()
{
// 創建socket套接字
SOCKET sListen = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (SOCKET_ERROR == sListen)
{
?? printf("Init Socket Error!\n");
?? return;
}

// 綁定socket到一個本地地址
sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.S_un.S_addr = INADDR_ANY;
if (::bind(sListen, (LPSOCKADDR)&sin, sizeof(sockaddr_in)) == SOCKET_ERROR)
{
?? printf("Bind Error!\n");
?? return;
}

// 設置socket進入監聽狀態
if (::listen(sListen, 10) == SOCKET_ERROR)
{
?? printf("Listen Error!\n");
?? return;
}

printf("Listening To Client...\n");

// 循環接收client端的連接請求
sockaddr_in ClientAddr;
int nAddrLen = sizeof(sockaddr_in);
SOCKET sClient;

while (INVALID_SOCKET == (sClient = ::accept(sListen, (sockaddr*)&ClientAddr, &nAddrLen)))
{
}

while (true == ProcessMsg(sClient))
{
}

// 關閉同客戶端的連接
::closesocket(sClient);

::closesocket(sListen);
}

bool InitSocket()
{
// 初始化socket dll
WSADATA wsaData;
WORD socketVersion = MAKEWORD(2, 2);
if (::WSAStartup(socketVersion, &wsaData) != 0)
{
?? printf("Init socket dll error\n");
?? return false;
}

return true;
}

bool CloseSocket()
{
// 釋放winsock庫
::WSACleanup();

if (NULL != g_pBuff)
{
?? delete [] g_pBuff;
?? g_pBuff = NULL;
}

return true;
}

bool ProcessMsg(SOCKET sClient)
{
int nRecv = ::recv(sClient, g_szBuff, MAX_PACKET_SIZE + 1, 0);
if (nRecv > 0)
{
?? g_szBuff[nRecv] = '\0';
}

// 解析命令
CCSDef::TMSG_HEADER* pMsgHeader = (CCSDef::TMSG_HEADER*)g_szBuff;
switch (pMsgHeader->cMsgID)
{
case MSG_FILENAME:??? // 文件名
?? {
??? OpenFile(pMsgHeader, sClient);
?? }
?? break;
case MSG_CLIENT_READY:?? // 客戶端準備好了,開始傳送文件
?? {
??? SendFile(sClient);
?? }
?? break;
case MSG_SENDFILESUCCESS: // 傳送文件成功
?? {
??? printf("Send File Success!\n");
??? return false;
?? }
?? break;
case MSG_FILEALREADYEXIT_ERROR: // 要保存的文件已經存在了
?? {
??? printf("The file reay to send already exit!\n");
??? return false;
?? }
?? break;
}

return true;
}

bool ReadFile(SOCKET sClient)
{
if (NULL != g_pBuff)
{
?? return true;
}

// 打開文件
FILE *pFile;
if (NULL == (pFile = fopen(g_szNewFileName, "rb")))?? // 打開文件失敗
{
?? printf("Cannot find the file, request the client input file name again\n");
?? CCSDef::TMSG_ERROR_MSG tMsgErrorMsg(MSG_OPENFILE_ERROR);
?? ::send(sClient, (char*)(&tMsgErrorMsg), sizeof(CCSDef::TMSG_ERROR_MSG), 0);
?? return false;
}

// 把文件的長度傳回到client去
fseek(pFile, 0, SEEK_END);
g_lLength = ftell(pFile);
printf("File Length = %d\n", g_lLength);
CCSDef::TMSG_FILELENGTH tMsgFileLength(g_lLength);
::send(sClient, (char*)(&tMsgFileLength), sizeof(CCSDef::TMSG_FILELENGTH), 0);

// 處理文件全路徑名,把文件名分解出來
char szDrive[_MAX_DRIVE], szDir[_MAX_DIR], szFname[_MAX_FNAME], szExt[_MAX_EXT];
_splitpath(g_szNewFileName, szDrive, szDir, szFname, szExt);
strcat(szFname,szExt);
CCSDef::TMSG_FILENAME tMsgFileName;
strcpy(tMsgFileName.szFileName, szFname);
printf("Send File Name: %s\n", tMsgFileName.szFileName);
::send(sClient, (char*)(&tMsgFileName), sizeof(CCSDef::TMSG_FILENAME), 0);

// 分配緩沖區讀取文件內容
g_pBuff = new char[g_lLength + 1];
if (NULL == g_pBuff)
{
?? return false;
}

fseek(pFile, 0, SEEK_SET);
fread(g_pBuff, sizeof(char), g_lLength, pFile);
g_pBuff[g_lLength] = '\0';
fclose(pFile);

return true;
}

// 打開文件
bool OpenFile(CCSDef::TMSG_HEADER* pMsgHeader, SOCKET sClient)
{
CCSDef::TMSG_FILENAME* pRequestFilenameMsg = (CCSDef::TMSG_FILENAME*)pMsgHeader;

// 對文件路徑名進行一些處理
char *p1, *p2;
for (p1 = pRequestFilenameMsg->szFileName, p2 = g_szNewFileName;
?? '\0' != *p1;
?? ++p1, ++p2)
{
?? if ('\n' != *p1)
?? {
??? *p2 = *p1;
?? }
?? if ('\\' == *p2)
?? {
??? *(++p2) = '\\';
?? }
}
*p2 = '\0';

ReadFile(sClient);

return true;
}

// 傳送文件
bool SendFile(SOCKET sClient)
{
if (NULL == g_pBuff)
{
?? ReadFile(sClient);
}

int nPacketBufferSize = MAX_PACKET_SIZE - 2 * sizeof(int); // 每個數據包存放文件的buffer大小
// 如果文件的長度大于每個數據包所能傳送的buffer長度那么就分塊傳送
for (int i = 0; i < g_lLength; i += nPacketBufferSize)
{??
?? CCSDef::TMSG_FILE tMsgFile;
?? tMsgFile.tFile.nStart = i;
?? if (i + nPacketBufferSize + 1> g_lLength)
?? {
??? tMsgFile.tFile.nSize = g_lLength - i;
?? }
?? else
?? {
??? tMsgFile.tFile.nSize = nPacketBufferSize;
?? }
?? //printf("start = %d, size = %d\n", tMsgFile.tFile.nStart, tMsgFile.tFile.nSize);
?? memcpy(tMsgFile.tFile.szBuff, g_pBuff + tMsgFile.tFile.nStart, tMsgFile.tFile.nSize);
?? ::send(sClient, (char*)(&tMsgFile), sizeof(CCSDef::TMSG_FILE), 0);
?? Sleep(0.5);
}

delete [] g_pBuff;
g_pBuff = NULL;

return true;
}

?

/*client.h同server.h*/

/*client.cpp*/

#include "client.h"

long g_lLength = 0;
char* g_pBuff = NULL;
char g_szFileName[MAXFILEDIRLENGTH];
char g_szBuff[MAX_PACKET_SIZE + 1];
SOCKET g_sClient;

// 初始化socket庫
bool InitSocket();
// 關閉socket庫
bool CloseSocket();
// 把用戶輸入的文件路徑傳送到server端
bool SendFileNameToServer();
// 與server端連接
bool ConectToServer();
// 打開文件失敗
bool OpenFileError(CCSDef::TMSG_HEADER *pMsgHeader);
// 分配空間以便寫入文件
bool AllocateMemoryForFile(CCSDef::TMSG_HEADER *pMsgHeader);
// 寫入文件
bool WriteToFile(CCSDef::TMSG_HEADER *pMsgHeader);
// 處理server端傳送過來的消息
bool ProcessMsg();

int main()
{
InitSocket();
ConectToServer();
CloseSocket();
return 0;
}

// 初始化socket庫
bool InitSocket()
{
// 初始化socket dll
WSADATA wsaData;
WORD socketVersion = MAKEWORD(2, 2);
if (::WSAStartup(socketVersion, &wsaData) != 0)
{
?? printf("Init socket dll error\n");
?? exit(-1);
}

return true;
}

// 關閉socket庫
bool CloseSocket()
{
// 關閉套接字
::closesocket(g_sClient);
// 釋放winsock庫
::WSACleanup();

return true;
}

// 與server端連接進行文件的傳輸
bool ConectToServer()
{
// 初始化socket套接字
if (SOCKET_ERROR == (g_sClient = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)))
{
?? printf("Init Socket Error!\n");
?? exit(-1);
}

sockaddr_in servAddr;
servAddr.sin_family = AF_INET;
servAddr.sin_port = htons(PORT);
servAddr.sin_addr.S_un.S_addr = ::inet_addr(SERVER_IP);
if (INVALID_SOCKET == (::connect(g_sClient, (sockaddr*)&servAddr, sizeof(sockaddr_in))))
{
?? printf("Connect to Server Error!\n");
?? exit(-1);
}

// 輸入文件路徑傳輸到server端
SendFileNameToServer();

// 接收server端傳過來的信息,直到保存文件成功為止
while (true == ProcessMsg())
{
}

return true;
}

// 把用戶輸入的文件路徑傳送到server端
bool SendFileNameToServer()
{
char szFileName[MAXFILEDIRLENGTH];
printf("Input the File Directory: ");

fgets(szFileName, MAXFILEDIRLENGTH, stdin);

// 把文件路徑發到server端
CCSDef::TMSG_FILENAME tMsgRequestFileName;
strcpy(tMsgRequestFileName.szFileName, szFileName);
if (SOCKET_ERROR == ::send(g_sClient, (char*)(&tMsgRequestFileName), sizeof(CCSDef::TMSG_FILENAME), 0))
{
?? printf("Send File Name Error!\n");
?? exit(-1);
}

return true;
}

// 處理server端傳送過來的消息
bool ProcessMsg()
{
CCSDef::TMSG_HEADER *pMsgHeader;
int nRecv = ::recv(g_sClient, g_szBuff, MAX_PACKET_SIZE + 1, 0);

pMsgHeader = (CCSDef::TMSG_HEADER*)g_szBuff;

switch (pMsgHeader->cMsgID)
{
case MSG_OPENFILE_ERROR:?? // 打開文件錯誤
?? {
??? OpenFileError(pMsgHeader);
?? }
?? break;
case MSG_FILELENGTH:??? // 文件的長度
?? {
??? if (0 == g_lLength)
??? {
???? g_lLength = ((CCSDef::TMSG_FILELENGTH*)pMsgHeader)->lLength;
???? printf("File Length: %d\n", g_lLength);
??? }
?? }
?? break;
case MSG_FILENAME:???? // 文件名
?? {
??? return AllocateMemoryForFile(pMsgHeader);
?? }
?? break;
case MSG_FILE:????? // 傳送文件,寫入文件成功之后退出這個函數
?? {
??? if (WriteToFile(pMsgHeader))
??? {
???? return false;
??? }
?? }
?? break;
}

return true;
}

// 打開文件失敗
bool OpenFileError(CCSDef::TMSG_HEADER *pMsgHeader)
{
if (NULL != g_pBuff)
?? return true;
assert(NULL != pMsgHeader);

printf("Cannot find file!Please input again!\n");

// 重新輸入文件名稱
SendFileNameToServer();

return true;
}

// 查找是否已經存在了要保存的文件,同時分配緩沖區保存文件
bool AllocateMemoryForFile(CCSDef::TMSG_HEADER *pMsgHeader)
{
assert(NULL != pMsgHeader);

if (NULL != g_pBuff)
{
?? return true;
}

CCSDef::TMSG_FILENAME* pRequestFilenameMsg = (CCSDef::TMSG_FILENAME*)pMsgHeader;
printf("File Name: %s\n", pRequestFilenameMsg->szFileName);

// 把文件的路徑設置為C盤根目錄下
strcpy(g_szFileName, "c:\\");
strcat(g_szFileName, pRequestFilenameMsg->szFileName);

// 查找相同文件名的文件是否已經存在,如果存在報錯退出
FILE* pFile;
if (NULL != (pFile = fopen(g_szFileName, "r")))
{
?? // 文件已經存在,要求重新輸入一個文件
?? printf("The file already exist!\n");
?? CCSDef::TMSG_ERROR_MSG tMsgErrorMsg(MSG_FILEALREADYEXIT_ERROR);
?? ::send(g_sClient, (char*)(&tMsgErrorMsg), sizeof(CCSDef::TMSG_ERROR_MSG), 0);

?? fclose(pFile);
?? return false;
}

// 分配緩沖區開始接收文件,如果分配成功就給server端發送開始傳送文件的要求
g_pBuff = new char[g_lLength + 1];
if (NULL != g_pBuff)
{
?? memset(g_pBuff, '\0', g_lLength + 1);
?? printf("Now ready to get the file %s!\n", pRequestFilenameMsg->szFileName);
?? CCSDef::TMSG_CLIENT_READY tMsgClientReady;

?? if (SOCKET_ERROR == ::send(g_sClient, (char*)(&tMsgClientReady), sizeof(CCSDef::TMSG_CLIENT_READY), 0))
?? {
??? printf("Send Error!\n");
??? exit(-1);
?? }
}
else
{
?? printf("Alloc memory for file error!\n");
?? exit(-1);
}

return true;
}

// 寫入文件
bool WriteToFile(CCSDef::TMSG_HEADER *pMsgHeader)
{
assert(NULL != pMsgHeader);

CCSDef::TMSG_FILE* pMsgFile = (CCSDef::TMSG_FILE*)pMsgHeader;

int nStart = pMsgFile->tFile.nStart;
int nSize = pMsgFile->tFile.nSize;
memcpy(g_pBuff + nStart, pMsgFile->tFile.szBuff, nSize);
if (0 == nStart)
{
?? printf("Saving file into buffer...\n");
}

memcpy(g_pBuff + nStart, pMsgFile->tFile.szBuff, nSize);
//printf("start = %d, size = %d\n", nStart, nSize);

// 如果已經保存到緩沖區完畢就寫入文件
if (nStart + nSize >= g_lLength)
{
?? printf("Writing to disk....\n");
?? // 寫入文件
?? FILE* pFile;
?? pFile = fopen(g_szFileName, "w+b");
?? fwrite(g_pBuff, sizeof(char), g_lLength, pFile);

?? delete [] g_pBuff;
?? g_pBuff = NULL;
?? fclose(pFile);

?? // 保存文件成功傳送消息給server退出server
?? CCSDef::TMSG_SENDFILESUCCESS tMsgSendFileSuccess;
?? while (SOCKET_ERROR == ::send(g_sClient, (char*)(&tMsgSendFileSuccess), sizeof(CCSDef::TMSG_SENDFILESUCCESS), 0))
?? {
?? }

?? printf("Save the file %s success!\n", g_szFileName);

?? return true;
}
else
{
?? return false;
}
}


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/254332.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/254332.shtml
英文地址,請注明出處:http://en.pswp.cn/news/254332.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

三種方式在CentOS 7搭建KVM虛擬化平臺

KVM 全稱是基于內核的虛擬機&#xff08;Kernel-based Virtual Machine&#xff09;&#xff0c;它是一個 Linux的一個內核模塊&#xff0c;該內核模塊使得 Linux變成了一個Hypervisor&#xff1a;它由 Quramnet開發&#xff0c;該公司于 2008年被 Red Hat 收購 KVM的整體結構&…

(五)EasyUI使用——datagrid數據表格

DataGrid以表格形式展示數據&#xff0c;并提供了豐富的選擇、排序、分組和編輯數據的功能支持。DataGrid的設計用于縮短開發時間&#xff0c;并且使開發人員不需要具備特定的知識。它是輕量級的且功能豐富。單元格合并、多列標題、凍結列和頁腳只是其中的一小部分功能。具體功…

拾取模型的原理及其在THREE.JS中的代碼實現

1. Three.js中的拾取 1.1. 從模型轉到屏幕上的過程說開 由于圖形顯示的基本單位是三角形&#xff0c;那就先從一個三角形從世界坐標轉到屏幕坐標說起&#xff0c;例如三角形abc 乘以模型視圖矩陣就進入了視點坐標系&#xff0c;其實就是相機所在的坐標系&#xff0c;如下圖&am…

StringBuilder-C#字符串對象

博主寫作不容易&#xff0c;孩子需要您鼓勵 萬水千山總是情 , 先點個贊行不行 在C# 中&#xff0c;string是引用類型&#xff0c;每次改變string類對象的值&#xff0c;即修改字符串變量對應的字符串&#xff0c;都需要在內存中為新的字符串重新分配空間。在默寫特定的情況…

java 19 - 11 異常的注意事項

1 /*2 * 異常注意事項:3 * A:子類重寫父類方法時&#xff0c;子類的方法必須拋出相同的異常或父類異常的子類。(父親壞了,兒子不能比父親更壞)4 * B:如果父類拋出了多個異常,子類重寫父類時,只能拋出相同的異常或者是他的子集,子類不能拋出父類沒有的異常5 * C:如果被重寫的…

數組去重的各種方式對比

數組去重&#xff0c;是一個老生常談的問題了&#xff0c;在各廠的面試中也會有所提及&#xff0c;接下來就來細數一下各種數組去重的方式吧&#xff1b; 對于以下各種方式都統一命名為 unique&#xff0c;公用代碼如下&#xff1a; // 生成一個包含100000個[0,50000)隨機數的數…

Linux平臺Makefile文件的編寫基礎篇和GCC參數詳解

問&#xff1a;gcc中的-I.是什么意思。。。。看到了有的是gcc -I. -I/usr/xxxxx..那個-I.是什么意思呢 最佳答案 答&#xff1a;-Ixxx 的意思是除了默認的頭文件搜索路徑(比如/usr/include等&#xff09;外&#xff0c;同時還在路徑xxx下搜索需要被引用的頭文件。 所以你的gcc …

舊知識打造新技術--AJAX學習總結

AJAX是將舊知識在新思想的容器內進行碰撞產生的新技術&#xff1a;推翻傳統網頁的設計技術。改善用戶體驗的技術。 學習AJAX之初寫過一篇《與Ajax的初次謀面》。當中都僅僅是一些自己淺顯的理解&#xff0c;這次就總結一下它在歷史長河中的重要地位。 【全】 AJAX全稱為Asnychr…

C#數組基本操作

文章目錄簡介數組排序和反轉語法實例查找數組元素語法實例數組元素求和、最大值、最小值、平均值語法實例數組字符串相互轉化語法實例在字符串中查找、刪除字符數組元素語法實例博主寫作不容易&#xff0c;孩子需要您鼓勵 萬水千山總是情 , 先點個贊行不行 簡介 C#提供了許…

redis(一)--認識redis

Redis官網對redis的定義是&#xff1a;“Redis is an open source, BSD licensed, advanced key-value cache and store”&#xff0c;可以看出&#xff0c;Redis是一種鍵值系統&#xff0c;可以用來緩存或存儲數據。Redis是“Remote Dictionary Server”&#xff08;遠程字典服…

轉:如何用gcc編譯生成動態鏈接庫*.so文件 動態庫

轉&#xff1a;如何編譯.so動態庫問&#xff1a;我源文件為main.c, x.c, y.c, z.c,頭文件為x.h,y.h,z.h如何編譯成.so動態庫&#xff1f;編譯器用gcc最好能給出詳細參數解釋&#xff0c;謝謝答&#xff1a;# 聲稱動代連接庫&#xff0c;假設名稱為libtest.sogcc x.c y.c z.c -f…

工業鏡頭的主要參數與選型

文章目錄簡介1、鏡頭的分類(1) 以鏡頭安裝分類(2) 以攝像頭鏡頭規格分類(3) 以鏡頭光圈分類(4) 以鏡頭的視場大小分類(5) 從鏡頭焦距上分2、選擇鏡頭的技術依據(1) 鏡頭的成像尺寸(2) 鏡頭的分辨率(3) 鏡頭焦距與視野角度(4) 光圈或通光量3、變焦鏡頭&#xff08;zoom lens&…

SQLSEVER 中的那些鍵和約束

SQL Server中有五種約束類型&#xff0c;各自是 PRIMARY KEY約束、FOREIGN KEY約束、UNIQUE約束、DEFAULT約束、和CHECK約束。查看或者創建約束都要使用到 Microsoft SQL Server Managment Studio。1. PRIMARY KEY約束 在表中常有一列或多列的組合&#xff0c;其值能唯一標識表…

數據庫 sqlite 進階

http://www.cppblog.com/czy463/archive/2013/12/16/204816.html 董淳光 前序&#xff1a; Sqlite3 的確很好用。小巧、速度快。但是因為非微軟的產品&#xff0c;幫助文檔總覺得不夠。這些天再次研究它&#xff0c;又有一些收獲&#xff0c;這里把我對 sqlite3 的研究列出來&a…

形象的列舉-C# 枚舉

文章目錄簡介例子分析點撥博主寫作不容易&#xff0c;孩子需要您鼓勵 萬水千山總是情 , 先點個贊行不行 簡介 枚舉類型用于聲明一組命名常數。 定義枚舉類型語法格式如下&#xff1a;enum 枚舉數組名{枚舉成員列表};例如&#xff1a; enum week{星期一&#xff0c;星期二…

Confluence 6 手動備份站點

2019獨角獸企業重金招聘Python工程師標準>>> Confluence 被配置自動備份數據&#xff0c;使用壓縮的 XML 格式。同時你也可以通過 Confluence 的 管理員控制臺&#xff08;Administration Console&#xff09;手動進行備份。 你需要具有 System Administrator 權限才…

編寫高質量的Makefile

分類&#xff1a; c/c研究 GNU&amp;LINUX2010-09-12 15:31163人閱讀 評論(0)收藏舉報源地址 &#xff1a;http://acm.hrbeu.edu.cn/forums/index.php?showtopic1827&st0&gopid8924&#entry8924 一、前言 回想自己的第一個Makefile&#xff0c;是這個樣子的 …

第六篇:python基礎之文件處理

第六篇&#xff1a;python基礎之文件處理 閱讀目錄 一.文件處理流程二.基本操作2.1 文件操作基本流程初探2.2 文件編碼2.3 文件打開模式2.4 文件內置函數flush2.5 文件內光標移動2.6 open函數詳解2.7 上下文管理2.8 文件的修改一.文件處理流程 打開文件&#xff0c;得到文件句柄…

前端每日實戰:56# 視頻演示如何用純 CSS 描述程序員的生活

效果預覽 按下右側的“點擊預覽”按鈕可以在當前頁面預覽&#xff0c;點擊鏈接可以全屏預覽。 https://codepen.io/comehope/pen/YvYVvY 可交互視頻 此視頻是可以交互的&#xff0c;你可以隨時暫停視頻&#xff0c;編輯視頻中的代碼。 請用 chrome, safari, edge 打開觀看。 ht…

從特殊到一般-C#中的類

文章目錄類的概念類的定義實例例子分析類的成員數據成員屬性成員方法成員靜態成員博主寫作不容易&#xff0c;孩子需要您鼓勵 萬水千山總是情 , 先點個贊行不行 類的概念 在日常生活中&#xff0c;類是對具有相同特性的一類是物的抽象。比如水果是一個類&#xff0c;它是對…