**TCP與UDP差別總結:
1、TCP面向連接配接(如打電話要先撥号建立連接配接);UDP是無連接配接的,即發送資料之前不需要建立連接配接
2、TCP提供可靠的服務。也就是說,通過TCP連接配接傳送的資料,無差錯,不丢失,不重複,且按序到達;UDP盡最大努力傳遞,即不保 證可靠傳遞
3、TCP面向位元組流,實際上是TCP把資料看成一連串無結構的位元組流;UDP是面向封包的
UDP沒有擁塞控制,是以網絡出現擁塞不會使源主機的發送速率降低(對實時應用很有用,如IP電話,實時視訊會議等)
4、每一條TCP連接配接隻能是點到點的;UDP支援一對一,一對多,多對一和多對多的互動通信
5、TCP首部開銷20位元組;UDP的首部開銷小,隻有8個位元組
6、TCP的邏輯通信信道是全雙工的可靠信道,UDP則是不可靠信道**
TCP協定
#include <WinSock2.h>
#include <stdio.h>
#include <stdlib.h>
#pragma comment(lib, "ws2_32.lib")
void Sever()
{
WSADATA wsaData;
char buf[] = "Server: hello, I am a server.....";
if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
printf("Failed to load Winsock");
return;
}
//建立用于監聽的套接字
SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0);
SOCKADDR_IN addrSrv;
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(tcp_port); //1024以上的端口号,需要設定,參考udp
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//這裡是接收自本機,可設定自己的需要的ip
int retVal = bind(sockSrv, (LPSOCKADDR)&addrSrv, sizeof(SOCKADDR_IN));
if(retVal == SOCKET_ERROR){
printf("Failed bind:%d\n", WSAGetLastError());
return;
}
if(listen(sockSrv,10) ==SOCKET_ERROR){
printf("Listen failed:%d", WSAGetLastError());
return;
}
SOCKADDR_IN addrClient;
int len = sizeof(SOCKADDR);
while(1)
{
//等待客戶請求到來
SOCKET sockConn = accept(sockSrv, (SOCKADDR *) &addrClient, &len);
if(sockConn == SOCKET_ERROR){
printf("Accept failed:%d", WSAGetLastError());
break;
}
printf("Accept client IP:[%s]\n", inet_ntoa(addrClient.sin_addr));
//發送資料,這裡可注釋掉
int iSend = send(sockConn, buf, sizeof(buf) , 0);
if(iSend == SOCKET_ERROR){
printf("send failed");
break;
}
char recvBuf[100];
memset(recvBuf, 0, sizeof(recvBuf));
// //接收資料
recv(sockConn, recvBuf, sizeof(recvBuf), 0);
printf("%s\n", recvBuf);
closesocket(sockConn);
}
closesocket(sockSrv);
WSACleanup();
}
void Client()
{
//加載套接字
WSADATA wsaData;
char buff[1024];
memset(buff, 0, sizeof(buff));
if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
printf("Failed to load Winsock");
return;
}
SOCKADDR_IN addrSrv;
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(tcp_port);//需要發送的port
addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//設定要發送的ip
//建立套接字
SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);
if(SOCKET_ERROR == sockClient){
printf("Socket() error:%d", WSAGetLastError());
return;
}
//向伺服器發出連接配接請求
if(connect(sockClient, (struct sockaddr*)&addrSrv, sizeof(addrSrv)) == INVALID_SOCKET){
printf("Connect failed:%d", WSAGetLastError());
return;
}else
{
//接收資料,這句話注釋掉
recv(sockClient, buff, sizeof(buff), 0);
printf("%s\n", buff);
}
//發送資料
char buffer = "hello, this is a Client....";
send(sockClient, buffer, sizeof(buffer), 0);
//關閉套接字
closesocket(sockClient);
WSACleanup();
}
頭檔案UDP_MODE.h
#include <WINSOCK2.H>
#include <stdio.h>
#include "fstream"
#pragma comment(lib,"WS2_32.lib")
#define BUF_SIZE 64
void LoadPara();
int Client(std::string& File_Path);
int Server(std::string Sim_Name_Path);
函數UDP_MODE.cpp
//加載參數,友善config檔案調用
char facedetectip[256];
int port_client;
int port_server;
void LoadPara()
{
LPCWSTR strPath(TEXT("./Setting.ini"));
LPCWSTR strTitle(TEXT("Parameter"));
LPCWSTR strKey;
const int BUFF_LEN = 128;//讀取字元串的緩存
TCHAR buff[BUFF_LEN];
int iLength = 0;
strKey = TEXT("FaceDetectIP");//facedetectip
GetPrivateProfileString(strTitle, strKey, L"127.0.0.1", buff, BUFF_LEN, strPath);
iLength = WideCharToMultiByte(CP_ACP, 0, buff, -1, NULL, 0, NULL, NULL);
WideCharToMultiByte(CP_ACP, 0, buff, -1, facedetectip, iLength, NULL, NULL);
strKey = TEXT("port_client"); //資料庫端口号
port_client = GetPrivateProfileInt(strTitle, strKey, 3306, strPath);
strKey = TEXT("port_server"); //資料庫端口号
port_server = GetPrivateProfileInt(strTitle, strKey, 3306, strPath);
}
//資料接收
int Server(std::string& File_Path)
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(1, 1);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0)
{
return -1;
}
if (LOBYTE(wsaData.wVersion) != 1 ||
HIBYTE(wsaData.wVersion) != 1)
{
WSACleanup();
return -1;
}
SOCKET sockSrv = socket(AF_INET, SOCK_DGRAM, 0);
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(port_client);
bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
SOCKADDR_IN addrClient;
int len = sizeof(SOCKADDR);
char recvBuf[64];
recvfrom(sockSrv, recvBuf, sizeof(recvBuf), 0, (SOCKADDR*)&addrClient, &len);
File_Path = recvBuf;
closesocket(sockSrv);
WSACleanup();
return 0;
}
//資料發送端
void Client(std::string Sim_Name_Path)
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(1, 1);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0)
{
return -1;
}
if (LOBYTE(wsaData.wVersion) != 1 ||
HIBYTE(wsaData.wVersion) != 1)
{
WSACleanup();
return -1;
}
SOCKET sockClient = socket(AF_INET, SOCK_DGRAM, 0);
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr = inet_addr(facedetectip);
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(port_server);
sendto(sockClient, Sim_Name_Path.c_str(), strlen(Sim_Name_Path.c_str()) + 1, 0,
(SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
closesocket(sockClient);
WSACleanup();
return 0
}
Http
需要安裝編譯curl:
通過curl+vs2015+openssl(vs2015必須需要這個)生成libcurl.lib
将生成的lib和include放置在配置裡,并加上Ws2_32.lib Wldap32.lib
在預定義中加上BUILDING_LIBCURL, CURL_STATICLIB
TaskHttpSender 用戶端發送
#include <string>
#include<iostream>
#include <curl/curl.h>
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "wldap32.lib")
#pragma comment(lib, "libcurl.lib")
bool send(const std::string &file/*要儲存的檔案名*/, std::string m_url/*http位址*/)
{
curl_global_init(CURL_GLOBAL_ALL);
CURL* m_hCurl = curl_easy_init();
curl_slist* pOptionList = NULL;
pOptionList = curl_slist_append(pOptionList, "Expect:");
curl_easy_setopt(m_hCurl, CURLOPT_HTTPHEADER, pOptionList);
curl_httppost* pFormPost = NULL;
curl_httppost* pLastElem = NULL;
//上傳檔案,指定本地檔案完整路徑
curl_formadd(&pFormPost, &pLastElem, CURLFORM_COPYNAME, "sendfile",
CURLFORM_FILE, file.c_str(), CURLFORM_CONTENTTYPE,
"application/octet-stream", CURLFORM_END);
curl_formadd(&pFormPost, &pLastElem,
CURLFORM_COPYNAME, "filename",
CURLFORM_COPYCONTENTS, file.c_str(),
CURLFORM_END);
//不加一個結束的hfs服務端無法寫入檔案,一般不存在這種問題,這裡加入隻是為了測試.
curl_formadd(&pFormPost, &pLastElem, CURLFORM_COPYNAME, "end", CURLFORM_COPYCONTENTS, "end", CURLFORM_END);
curl_easy_setopt(m_hCurl, CURLOPT_HTTPPOST, pFormPost);
curl_easy_setopt(m_hCurl, CURLOPT_URL, m_url.c_str());
CURLcode res = curl_easy_perform(m_hCurl);
if (res != CURLE_OK)
{
std::cout << res << std::endl;
return false;
}
else
std::cout << "success" << std::endl;
curl_formfree(pFormPost);
return true;
}
TaskHttpRecver 服務端接受
#include <string>
#include <cstdio>
#include<iostream>
#include <curl/curl.h>
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "wldap32.lib")
#pragma comment(lib, "libcurl.lib")
bool recv(std::string m_filename/*要儲存的檔案名*/, std::string m_url/*http位址*/)
{
std::string filePath = m_filename;
FILE *m_fp = fopen(filePath.c_str(), "w");
if (!m_fp)
{
return false;
}
curl_global_init(CURL_GLOBAL_ALL);
CURL* m_hCurl = curl_easy_init();
//設定接收資料的回調
curl_easy_setopt(m_hCurl, CURLOPT_URL, m_url.c_str());
curl_easy_setopt(m_hCurl, CURLOPT_WRITEFUNCTION, DownloadCallback);
curl_easy_setopt(m_hCurl, CURLOPT_WRITEDATA, m_fp);
curl_easy_setopt(m_hCurl, CURLOPT_MAXREDIRS, 5);
curl_easy_setopt(m_hCurl, CURLOPT_FOLLOWLOCATION, 1);
CURLcode retcCode = curl_easy_perform(m_hCurl);
if (retcCode != CURLE_OK)
std::cout << retcCode << std::endl;
else
std::cout << "success" << std::endl;
curl_easy_cleanup(m_hCurl);
fclose(m_fp);
m_fp = nullptr;
return true;
}
size_t DownloadCallback(void* pBuffer, size_t nSize, size_t nMemByte, void* pParam)
{
FILE* fp = (FILE*)pParam;
size_t nWrite = fwrite(pBuffer, nSize, nMemByte, fp);
return nWrite;
}