1. udp和tcp最大的區別:
1) tcp最大的特點就是面向連線、安全可靠,也就是說tcp通訊必須要先建立連線,並且通訊過程需要時時校驗,如果資料有誤需要重發;
2) udp最大的特點就是面向無連線,不可靠,也就是說不用建立連線就直接向目標傳送資訊,並且通訊過程中不做任何校驗,如果資料丟失或者有誤也不管;
2. udp的sockets程式設計:
1) 首先最大的特點就是客戶端不需要使用connect連線,伺服器端也不需要listen來監聽請求,但不過建立套接字的過程還是和tcp一樣的;
2) 伺服器端不需要accept了,因為不需要監聽,而是直接可以用recvfrom函式接受客戶端傳送的資料!
3) 而客戶端由於不需要connect連線伺服器端,因此可以直接使用sendto函式向目標伺服器傳送資料;
4) 雙方都可以直接使用sendto和recvfrom進行資料通訊;
5) udp套接字的配置:
i. 首先需要在socket()函式中指定為sock_dgram,即資料報套接字型別(基於udp);
ii. 在tcp中,資料收發必須持有對方的套接字,而伺服器端監聽、接收請求必須持有本地的套接字,一般需要兩個套接字來支援;
iii. 但是在udp中,通訊雙方只能持有乙個套接字,即都是本地的套接字,傳送的時候需要指定對方的套接字位址,而接收的時候需要用乙個空的套接字位址接收對方的位址,即收發時sendto和recvfrom中的套接字控制代碼s都是繫結了本地位址的套接字,收發統統必須持有自己的套接字;
iv. 也就是說資料收發的快取都是用本地套接字!而tcp中資料收發的快取都是用對方的套接字(建立在本地程式中);
v. 因此,雙方在收發資料之前必須先對本地位址進行繫結,伺服器端仍然可以使用bind進行顯示的繫結,但是在winsock手冊中明確講了不支援在客戶端中使用bind來顯示繫結自己的位址,因為顯示繫結往往需要你輸入精確的位址,而有些時候位址是動態分配的,每次使用的都可能不一樣,因此不推薦在客戶端中顯示的使用bind來繫結自己的位址;
vi. 還好,sendto函式在第一次呼叫的時候就能隱式地繫結當前的位址,由於伺服器端只能被動地等待請求,因此不可能比recvfrom先呼叫sendto,所以伺服器端要先使用bind來繫結本地位址,而客戶端必須主動請求向伺服器端傳送資訊,因此不肯能比sendto先呼叫recvfrom,因此sendto一定先呼叫,而呼叫的同時也自動繫結了本地位址了;
6) sendto:
i. 函式原型:
int sendto(
socket s, // 繫結中本地位址的套接字
const char far* buf, // 傳送資料的快取
int len, // 資料的長度(位元組)
int flags, // 函式呼叫模式,一般為0
const struct sockaddr far* to, // 目標位址
int tolen, // 目標位址結構的大小
);
ii. 該函式將返回實際傳送的位元組數,當然可能小於指定的位元組數,如果失敗則會返回相應的錯誤碼;
7) recvfrom:
i. 函式原型:
int recvfrom(
socket s, // 繫結本地位址的套接字
char far* buf, // 接受資料的快取
int len, // 接受多少位元組
int flags, // 一般為0
struct sockaddr far* from, //用於接受資料來源的位址
int far* fromlen // 資料來源的位址的大小(位元組)
);
ii. 該函式將返回實際收到的位元組數,如果套接字被正常關閉將返回0,否則將返回錯誤碼;
!!下面將演示乙個簡單的udp通訊例項,實現的內容和上乙個tcp通訊例項一樣;
伺服器端:
#include #include #include #pragma comment(lib, "ws2_32.lib")
int main() ;
wsadata data;
word wversionrequired = makeword(2, 0);
wsastartup(wversionrequired, &data);
socket s = socket(af_inet, sock_dgram, 0);
sockaddr_in addr;
addr.sin_family = af_inet;
addr.sin_port = htons(75);
addr.sin_addr.s_un.s_addr = inaddr_any;
bind(s, (sockaddr*)&addr, sizeof(addr));
printf("server is setup and now waiting for clients' request...\n");
sockaddr_in addrclient;
int nsockaddrsize = sizeof(addrclient);
if (recvfrom(s, szbuff, sizeof(szbuff), 0, (sockaddr*)&addrclient, &nsockaddrsize) > 0)
closesocket(s);
wsacleanup();
if (getchar()) return 0;
return 0;
}
客戶端:
#include #include #include #pragma comment(lib, "ws2_32.lib")
int main() ;
wsadata data;
word wversionrequested = makeword(2, 0);
wsastartup(wversionrequested, &data);
socket s = socket(af_inet, sock_dgram, 0);
sockaddr_in addr;
addr.sin_family = af_inet;
addr.sin_port = htons(75);
addr.sin_addr.s_un.s_addr = inet_addr("127.0.0.1");
printf("client is setup and now trying to connect server...\n");
sockaddr_in addrserver;
int nsockaddrsize = sizeof(addrserver);
sendto(s, szsendtoserver, sizeof(szsendtoserver), 0, (sockaddr*)&addr, nsockaddrsize);
recvfrom(s, szbuff, sizeof(szbuff), 0, (sockaddr*)&addrserver, &nsockaddrsize);
printf("%s\n", szbuff);
closesocket(s);
wsacleanup();
if (getchar()) return 0;
return 0;
}
MFC TCP通訊的簡單實現
以下演示的是乙個使用tcp協議的客戶端和伺服器端實現 即流式套接字 客戶端請求連線,伺服器端回送給客戶端一句話 1.伺服器端 include include include pragma comment lib,ws2 32.lib 如果沒有ws2 32.dll則顯示鏈結靜態庫!int main 關...
UDP通訊的簡單實現(程式)
資訊處理介面,定義了資訊的關閉,傳送,和接收 public inte ce messageaction udp類實現了messageaction封裝了下面的資訊,並提供了相應的get和set方法private int sendport 要傳送資料的埠號埠號 private int localport...
通訊錄的簡單實現!!!
1.因為程式 較多,為了避免程式過於繁雜,將程式分成了兩個.c檔案 contact.c 和 test.c 和乙個contact h檔案。2.cantact.h檔案內容主要包括函式名和結構體的定義。3.contact.c檔案主要用於定義函式的實現,而test.c則主要起到測試的作用1.contact ...