『壹』 怎麼樣用出c語言寫一個分析TCP/IP報文的程
socket編程寫了一個簡單的DNS伺服器。
是這樣實現的,用兩台PC,一個做客戶端,一個做伺服器;
在伺服器用socket監視53埠,recvfrom()函數負責接收DNS查詢報文,將其存入事先寫好的數據結構里;
因為DNS查詢報文和應答報文的前部分欄位格式都是一樣的,只是修改了幾個參數,然後重點把DNS應答報文後面的欄位進行增添。
然後用sendto();函數發送就可以了。
在ie裡面輸入任意的網址,回車,就會觸發客戶端向伺服器發出DNS查詢報文,
此時你可以同時在伺服器和客戶端抓包,看收到的報文是否正確。
注意幾點:
1、一定要熟悉報文結構,定義合適的結構體,將報文進行解析
2、一定要注意網路序和主機序的轉換htonl(),htons(),ntohl(),ntohs()等
3、找個熟知埠,最好是你熟悉的協議,如ftp,http,dns等。
4、客戶端要把DNS伺服器配置為你的伺服器ip。
『貳』 關於tcp協議中服務端字元串的接受,截取和處理···
如果長度是固定的,可以根據長度判斷,要是不固定的用數組形式發送,接受後分割數組,假如:
A|B|C,是個數組,接收後,分割數組,得到,A,B,C,再將A作為對比,B和C作為參數!
你用的是什麼語言?
『叄』 怎樣用c語言或者c++實現tcp,並實現文本傳輸
TCP協議實現文件傳輸
使用TCP協議實現傳輸文件
程序分為發送端和接收端。首先在傳輸文件數據之前,發送端會把將裝有文件名稱和文件長度等
信息的數據包發送至接收端。接收端收到文件名稱和文件長度信息後會創建好空白文件。接著開始傳輸
文件數據。下面介紹實現功能的主要過程:
1.創建套接字、綁定、監聽、連接、接受連接
//創建TCP協議的套接字
m_Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(SOCKET_ERROR == m_Socket)
AfxMessageBox("Create Socket Error! ", 0, 0);
//綁定與監聽
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.s_addr = inet_addr(sIP);
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(Port);
int ret = bind(m_Socket, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));
if(ret==SOCKET_ERROR)
AfxMessageBox("Bind Socket Error!", 0, 0);
//連接
SOCKADDR_IN ServerAddr;
ServerAddr.sin_addr.s_addr = inet_addr(ServerAddr_in);
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_port = htons(ServerPort);
int Result = connect(m_Socket, (struct sockaddr*)&ServerAddr, sizeof(struct sockaddr));
if(SOCKET_ERROR == Result)
AfxMessageBox("Connet Failed!");
//接受連接
SOCKADDR_IN ClientAddr;
int len = sizeof(SOCKADDR_IN);
SOCKET ClientSock = accept(m_Socket, (struct sockaddr*)&ClientAddr, &len);
if(SOCKET_ERROR == ClientSock)
AfxMessageBox("Accept Failed!");
2.聲明宏和結構體
聲明套接字緩沖區和一次發送文件數據的緩沖區大小
#define SOCKET_BUFF 80000 //套接字緩沖區大小
#define PACK_BUFF 50000 //數據包緩沖區大小
聲明文件I/O緩沖區和最大文件路徑長度
#define FILE_NAME_MAX 100 //文件路徑最大長度
#define FILE_IO_BUFF PACK_BUFF //文件IO緩沖區
//文件信息
typedef struct _FileInfor
{
u_long ulFileLen;
char sFileName[ FILE_NAME_MAX ];
}_FileInfor;
//數據包
typedef struct _DataPack
{
char cType; //'D'為數據 'M'為文件信息
int nPackLen;
char sContent[ PACK_BUFF ]; //數據包緩沖區
u_long nPosition; //數據在文件中的位置
int nContentLen; //數據位元組數
_FileInfor FileInfor; //文件信息
}_DataPack;
3.發送端
//發送線程需要的全局變數
char sPath[FILE_NAME_MAX]; //文件地址
u_long FileByteCount; //文件大小
SOCKET ClientSocket; //
(1)設置套接字發送緩沖區大小,在32位Windows XP環境下,系統為每個套接字分配的默認發送數據緩
沖區為8192位元組。由於傳輸的文件很大,可能幾十兆,或者更大。那麼系統為每個套接字分配的默認
緩沖區顯然過小。為此在創建套接字之後,需要修改套接字發送數據緩沖尺寸。在這里我修改為80k,
差不多可以夠用了。
//設置套接字發送緩沖區
int nBuf = SOCKET_BUFF;
int nBufLen = sizeof(nBuf);
int nRe = setsockopt(ClientSock, SOL_SOCKET, SO_SNDBUF, (char*)&nBuf, nBufLen);
if(SOCKET_ERROR == nRe)
AfxMessageBox("setsockopt error!");
//檢查緩沖區是否設置成功
nRe = getsockopt(ClientSock, SOL_SOCKET, SO_SNDBUF, (char*)&nBuf, &nBufLen);
if(SOCKET_BUFF != nBuf)
AfxMessageBox("檢查緩沖區:setsockopt error!");
(2)測量文件大小並發送文件大小和名稱給客戶端
首先使用C庫函數對源文件進行測量
//得到文件地址
LPTSTR lpPath = m_sPath.GetBuffer( m_sPath.GetLength ());
//打開文件
FILE *File = fopen(lpPath, "rb");
if(NULL == File)
AfxMessageBox("打開文件失敗!");
//測量文件大小
char Buff[PACK_BUFF];
u_long ulFaceReadByte;
FileByteCount = 0;
fseek(File, 0, SEEK_SET);
while(!feof(File))
{
ulFaceReadByte = fread(Buff, 1, 1, File);
FileByteCount += ulFaceReadByte;
}
//關閉文件
int nRe = fclose(File);
if(nRe)
AfxMessageBox("關閉文件失敗!");
此時以獲取源文件的長度,我們將文件長度和文件名稱放到數據包中,設置數據包為'M'類型。
//打包
_DataPack Pack;
Pack.cType = 'M';
Pack.nPackLen = sizeof(Pack);
//取得文件名
ZeroMemory(Pack.FileInfor.sFileName, FILE_NAME_MAX);
GetFIieNameFromPath(lpPath, Pack.FileInfor.sFileName);
Pack.FileInfor.ulFileLen = FileByteCount;
接著使用send()將打包完成的數據包發送給接收端,把發送線程的全局變數初始化,並創建發送線
程,文件數據將由發送線程負責發送
//發送數據包 文件大小和名稱
nRe = send(m_ClientSockFd.fd_array[0], (char*)&Pack, Pack.nPackLen, 0);
if(SOCKET_ERROR == nRe)
AfxMessageBox("Send File Size Failed!");
//線程准備全局變數
strcpy(sPath, m_sPath);
ClientSocket = m_ClientSockFd.fd_array[0];
//啟動線程發送文件
DWORD ID;
m_hSendThread = CreateThread(0, 0, SendDataThrad, 0, 0, &ID);
(3)發送文件數據線程。先打開源文件,為了一次讀取大量數據將文件緩沖區設置為FILE_IO_BUFF大小,
然後將讀取的數據打包並發送。這樣不斷地讀、不斷地發送,直到將整個文件發送完為止。
DWORD __stdcall CServerDlg::SendDataThrad(LPVOID LpP)
{
//打開文件
FILE *File = fopen(sPath, "rb");
if(NULL == File)
{
AfxMessageBox("SendDataThrad中打開文件失敗!");
return 1;
}
//設置文件緩沖區
int nBuff = FILE_IO_BUFF;
if(setvbuf(File, (char*)&nBuff, _IOFBF, sizeof(nBuff)))
AfxMessageBox("設置文件緩沖區失敗!");
//讀取文件數據並發送
u_long ulFlagCount = 0; //記錄讀了多少數據
u_long FaceReadByte = 0; //一次實際讀取的位元組數
char sBuff[PACK_BUFF];
ZeroMemory(sBuff, PACK_BUFF);
fseek(File, 0, SEEK_SET);
while (!feof(File))
{
FaceReadByte = fread(sBuff, 1, PACK_BUFF, File);
//打包
_DataPack DataPack;
DataPack.cType = 'D';
DataPack.nPackLen = sizeof(DataPack);
DataPack.nContentLen = FaceReadByte;
CopyMemory(DataPack.sContent, sBuff, FaceReadByte);
DataPack.nPosition = ulFlagCount;
//發送
int nResult = send(ClientSocket, (char*)&DataPack, DataPack.nPackLen, 0);
if (SOCKET_ERROR == nResult)
{
AfxMessageBox("SendDataThrad中發送數據失敗!");
}else
ulFlagCount += FaceReadByte; //記錄發送位元組數
}
AfxMessageBox("發送結束");
//關閉
int nRe = fclose(File);
if(nRe)
AfxMessageBox("SendDataThrad中關閉文件失敗!");
return 0;
}
4.接收端
//接收線程用的全局變數
_FileInfor FileInfor; //文件信息
u_long ulWriteByte; //記錄總共寫入的位元組
char lpPath[FILE_NAME_MAX]; //文件路徑
char sFilePathAndName[FILE_NAME_MAX]; //完整的文件路徑
(1)設置套接字接收緩沖區大小。
//設置套接字接收緩沖區
int nBuf = SOCKET_BUFF;
int nBufLen = sizeof(nBuf);
SOCKET ClientSock = m_Sock.GetSocket();
int nRe = setsockopt(ClientSock, SOL_SOCKET, SO_RCVBUF, (char*)&nBuf, nBufLen);
if(SOCKET_ERROR == nRe)
AfxMessageBox("setsockopt error!");
//檢查緩沖區是否設置成功
nRe = getsockopt(ClientSock, SOL_SOCKET, SO_RCVBUF, (char*)&nBuf, &nBufLen);
if(SOCKET_BUFF != nBuf)
AfxMessageBox("檢查緩沖區:setsockopt error!");
(2)接收文件信息和文件數據線程。先判斷數據包是屬於文件信息還是文件類型,如果是文件信息就根
據信息創建空文件,如果是文件數據就將數據已追加的方式寫進目的文件中。
DWORD __stdcall CClientDlg::ReceiveDataPro(LPVOID LpP)
{
CSocket_Win32 *pCSock = (CSocket_Win32*)LpP;
u_long ulWriteByteCount = 0;
while (1)
{
_DataPack DataPack;
ZeroMemory(&DataPack, sizeof(DataPack));
if(!(*pCSock).Receive(&DataPack, sizeof(DataPack)))
{
AfxMessageBox("Receive DataPack Failed!");
}
//判斷數據包類型
if('M' == DataPack.cType) //包為文件信息
{
//接收文件信息
FileInfor.ulFileLen = DataPack.FileInfor.ulFileLen; //獲取文件長度
strcpy(FileInfor.sFileName, DataPack.FileInfor.sFileName); //獲取文件名稱
//得到文件目錄
char sFilePath[FILE_NAME_MAX];
ZeroMemory(sFilePath, FILE_NAME_MAX);
strcpy(sFilePath, lpPath);
strcat(sFilePath, FileInfor.sFileName);
strcat(sFilePathAndName, sFilePath); //保存完整的文件路徑
//創建文件
SECURITY_ATTRIBUTES attr;
attr.nLength = FileInfor.ulFileLen;
attr.lpSecurityDescriptor = NULL;
HANDLE hRe = CreateFile(sFilePath, GENERIC_WRITE, FILE_SHARE_WRITE, &attr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if(INVALID_HANDLE_VALUE == hRe)
AfxMessageBox("創建文件失敗!");
bool bRe = ::CloseHandle(hRe);
//可以開始接受文件
bIsStartReceive = true;
}else if('D' == DataPack.cType) //包為文件數據
{
//打開文件
char sPath[FILE_NAME_MAX];
strcpy(sPath, sFilePathAndName);
FILE *File = fopen(sPath, "ab");
if(0 == File)
AfxMessageBox("打開文件失敗!");
//設置文件緩沖區
int nBuff = FILE_IO_BUFF;
if(setvbuf(File, (char*)&nBuff, _IOFBF, sizeof(nBuff)))
AfxMessageBox("設置文件緩沖區失敗!");
//定位文件
u_long nPosition = DataPack.nPosition;
int nRe = fseek(File, nPosition, SEEK_SET);
if(nRe)
AfxMessageBox("SendDataThrad中定位失敗!");
//寫文件
u_long nNumberOfBytesWritten = fwrite(&DataPack.sContent, 1, DataPack.nContentLen, File);
if(DataPack.nContentLen != nNumberOfBytesWritten)
AfxMessageBox("寫文件失敗!");
else
{
ulWriteByteCount += nNumberOfBytesWritten;
}
fflush(File); //清除文件緩沖區
//關閉文件
nRe = fclose(File);
if(nRe)
AfxMessageBox("關閉文件失敗!");
if(ulWriteByteCount >= FileInfor.ulFileLen)
{
AfxMessageBox("接收結束");
break;
}
}
}
return 0;
}
『肆』 Windows系統用C語言寫TCP通信
#include
#include
#include
#pragma comment(lib,"ws2_32.lib")
typedef struct{
SOCKET accpt;
int lock;
}Arg;
void *transfer(void *arg)
{
Arg * info = (Arg *)arg;
SOCKET clientSock;
char recvbuf[102];
char sendBuf[] = "10";
int ret;
memcpy(&clientSock,(void*)&info->accpt,sizeof(clientSock));
info->lock =1;
while (TRUE)
{
ret = send(clientSock,sendBuf,2,0);
if (ret == -1)
{
break;
}
ret = recv(clientSock,recvbuf,102,0);
printf("%s\n",recvbuf);
}
return (void *)0;
}
void* timer(void *arg)
{
time_t last = time(NULL);
time_t now;
int i = 20;
while(i--)
{
now = time(NULL);
if(now - last == 1)
{
printf("1s past!\n");
last = now;
}
Sleep(500);
}
printf("timer exit.\n");
return (void *)0;
}
int main(void) {
WSADATA wsaData;
SOCKET ListenSocket;
SOCKADDR_IN service,client;
int len = sizeof(client);
Arg argument;
pthread_t tid;
char sendBuf[] = "ID=2;WHAT=host";
int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != NO_ERROR) {
printf("Error at WSAStartup()\n");
return 1;
}
ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ListenSocket == INVALID_SOCKET) {
printf("Error at socket(): %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr("127.0.0.1");
service.sin_port = htons(27115);
if (bind( ListenSocket,
(SOCKADDR*) &service,
sizeof(service)) == SOCKET_ERROR) {
printf("bind() failed.\n");
closesocket(ListenSocket);
WSACleanup();
return 1;
}
if (listen( ListenSocket, 1 ) == SOCKET_ERROR) {
printf("Error listening on socket.\n");
closesocket(ListenSocket);
WSACleanup();
return 1;
}
argument.lock = 1;
printf("Waiting for client to connect...\n");
pthread_create(&tid,NULL,timer,NULL);
while(TRUE){
argument.accpt = accept( ListenSocket, (SOCKADDR*)&client, &len );
if (argument.accpt == INVALID_SOCKET) {
printf("accept failed: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
} else {
printf("accept%s:%d\n",inet_ntoa(client.sin_addr),client.sin_port);
while (!argument.lock);
argument.lock = 0;
// sendto(argument.accpt,sendBuf,sizeof(sendBuf),0,(SOCKADDR*)&client,len);
pthread_create(&tid,NULL,transfer,&argument);
//send(AcceptSocket,sendBuf,sizeof(sendBuf),0);
}
}
// No longer need server socket
closesocket(ListenSocket);
WSACleanup();
return 0;
}
『伍』 c語言運行結果如何截屏
1 使用系統截屏功能。
需要使用按鍵print screen.在鍵盤上印的是prt sc。
單獨使用該鍵,會截整個屏幕,如果用alt+prt sc,則會截取當前窗口的部分。
截屏後,數據會報存在剪貼板中,這時可以打開系統畫圖工具,或者任意圖形編輯工具,粘貼。即可得到截屏後的數據,保存成文件即可。如果需要裁剪,也可以在這類工具中操作。
2 使用工具進行截屏。
目前提供快捷截屏的軟體很多,比如qq,搜狗輸入法,搜狗瀏覽器等都有截屏工具提供。
比如qq默認的截屏快捷鍵是ctrl+alt+a。同時按下三個鍵,會發現滑鼠箭頭變成彩色,這時點擊並選擇需要截屏的區域,雙擊即可完成截屏,將圖片保存在內存中。
也可以在截屏後,直接保存成文件。
『陸』 如何用tcpmp命令截完整的數據包
默認系統里邊沒有安裝有tcpmp的,無法直接使用這里我們可以使用yum來直接安裝它yuminstall-ytcpmp如果忘記了這個軟體的用法,我們可以使用tcpmp--help來查看一下使用方法一般我們的伺服器里邊只有一個網卡,使用tcpmp可以直接抓取數據包,但是這樣查看太麻煩了,所以都會添加參數來進行獲取的。例如我截取本機(192.168.31.147)和主機114.114.114.114之間的數據tcpmp-n-ieth0host192.168.31.147and114.114.114.114還有截取全部進入伺服器的數據可以使用以下的格式tcpmp-n-ieth0dst192.168.31.147或者伺服器有多個IP可以使用參數tcpmp-n-ieth0dst192.168.31.147or192.168.31.157我們抓取全部進入伺服器的TCP數據包使用以下的格式,大家可以參考下tcpmp-n-ieth0dst192.168.31.147or192.168.31.157andtcp從本機出去的數據包tcpmp-n-ieth0src192.168.31.147or192.168.31.157tcpmp-n-ieth0src192.168.31.147or192.168.31.157andport!22andtcp或者可以條件可以是or和and配合使用即可篩選出更好的結果。