1. 兩天電腦通訊需要協議,通訊的兩台電腦IP必須唯一
2. 同一個電腦可以進行多個應用程式與其他電腦通訊,IP地址唯一,而連接埠號碼是區別同一電腦(同一IP)的唯一標示。
3. 實際上就類似於一個辦公室的總機號碼(IP)和分機號碼(連接埠號碼)
4. 協議:為了進行網路中的資料交換(通訊)而建立的規則、標準或約定
5. 協議=語義+文法+規則
6. 不同層具有各自不同的協議
7. 上層使用下層提供的服務,實際通訊在最底層完成
8. 對等層實體之間虛擬通訊|
9. TCP:連線導向的可靠的傳輸協議
10. UDP:面向不需連線的不可靠的傳輸協議
11. 連接埠是一種抽象的軟體結構。應用程式通過系統調用與某連接埠建立串連後,傳輸層傳給連接埠的資料都被響應的進行所接收,相應進程發給傳輸層的資料都通過該連接埠輸出。
12. 連接埠用一個整數型標示符來表示。連接埠號碼跟協議相關,TCP/IP傳輸層的兩個協議TCP和UDP是完全獨立的兩個軟體模組,因此各自的連接埠號碼也相互獨立。
13. 連接埠使用一個16位的數字來表示,它的範圍是0~65535,1024以下的連接埠號碼保留給預定義的服務。例如:http使用的是80連接埠。
14. socket(通訊端):windows sockets只支援一個通訊地區:網際域(AF_INET),這個域被使用網際協議簇通訊的進程使用。
15. C/S模式:客戶機向伺服器提出請求,伺服器接收到請求後,提供相應的服務。
16. 通訊端的類型
a) 流式通訊端:(SOCK_STREAM):連線導向可靠的Data Transmission Service,按順序接收
b) 資料包式通訊端:(SOCK_DGRAM):無串連服務。接收順序混亂。
c) 原始通訊端(SOCK_RAM)
17. 基於TCP(連線導向)的socket編程
a) 伺服器端程式:
i. 建立通訊端socket
ii. 將通訊端綁定到一個本地地址和連接埠上bind
iii. 將通訊端設為監聽模式,準備接收客戶請求listen
iv. 等待客戶請求到了;當請求到來後,接收串連請求,返回一個新的對應於此次串連的通訊端accept
v. 用返回的通訊端和用戶端進行通訊rend/recv
vi. 返回,等待另一客戶請求
vii. 關閉通訊端
b) 用戶端程式:
i. 建立通訊端socket
ii. 向服務端發出串連請求connect
iii. 和伺服器端進行通訊rend/recv
iv. 關閉通訊端
18. 基於UDP的socket編程
a) 伺服器端(接收端)程式:
i. 建立通訊端socket
ii. 將通訊端綁定到一個本地地址和連接埠上bind
iii. 等待接收資料recv/from
iv. 關閉通訊端
b) 用戶端(發送端)程式:
i. 建立通訊端socket
ii. 向伺服器發送資料sendto
iii. 關閉通訊端
19. int WSAStartup (
WORD wVersionRequested, //打算使用的最高winsock版本號碼
LPWSADATA lpWSAData //是個結構體,接收socket的詳細資料
);
20. alt+F8:格式化代碼
21. 面向TCP的串連,伺服器端
a) 通訊端
SOCKET socket (
int af, //指定地址簇
int type, //socket類型
int protocol //協議
);
b) 綁定
int bind (
SOCKET s, //要綁定的通訊端
const struct sockaddr FAR* name, //指定了該通訊端的本地地址資訊
int namelen //該地址結構的長度
);
struct sockaddr {
u_short sa_family;
char sa_data[14];
};
c) 監聽
int listen (
SOCKET s,
int backlog
);
d) 接受串連
SOCKET accept (
SOCKET s,
struct sockaddr FAR* addr,
int FAR* addrlen
);
e) 發送
int send (
SOCKET s, //建立串連的socket
const char FAR * buf, //發送的資料
int len, //發送資料的長度
int flags
);
f) 接收
int recv (
SOCKET s,
char FAR* buf,
int len,
int flags
);
g) 需要的檔案
#include <winsock2.h>
需要串連一個動態連結程式庫:ws2_32.lib
22. 伺服器端:
a) Socket
b) 串連:connect
int connect (
SOCKET s,
const struct sockaddr FAR* name,
int namelen
);
c) 接收:recv
d) 發送:send
e) 關閉:closesocket
23. Tcp服務端程式:
#include <WINSOCK2.H>#include <stdio.h>void main(){WORD wVersionRequested;WSADATA wsaData;int err;wVersionRequested = MAKEWORD( 1, 1 );err = WSAStartup( wVersionRequested, &wsaData );if ( err != 0 ) {return;}if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) {WSACleanup( );return; }SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,0);SOCKADDR_IN addrSrv;addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);addrSrv.sin_family=AF_INET;addrSrv.sin_port=htons(6000);bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));listen(sockSrv,5);SOCKADDR_IN addrClient;int len=sizeof(SOCKADDR);while(1){SOCKET sockConn=accept(sockSrv,(SOCKADDR*)&addrClient,&len);char sendBuf[100];sprintf(sendBuf,"Welcome %s to 劉窪村",inet_ntoa(addrClient.sin_addr));send(sockConn,sendBuf,strlen(sendBuf)+1,0);char recvBuf[100];recv(sockConn,recvBuf,100,0);printf("%s\n",recvBuf);closesocket(sockConn);}}
24. Tcp用戶端程式:
#include <WINSOCK2.H>#include <stdio.h>void main(){WORD wVersionRequested;WSADATA wsaData;int err;wVersionRequested = MAKEWORD( 1, 1 );err = WSAStartup( wVersionRequested, &wsaData );if ( err != 0 ) {return;}if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) {WSACleanup( );return; }SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0);SOCKADDR_IN addrSrv;addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");//伺服器端的地址addrSrv.sin_family=AF_INET;addrSrv.sin_port=htons(6000);connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));char recvBuf[100];recv(sockClient,recvBuf,100,0);printf("%s\n",recvBuf);send(sockClient,"This is 劉窪村",strlen("This is 劉窪村")+1,0);closesocket(sockClient);WSACleanup();}
25. 運行之後,開啟了6個用戶端,一個伺服器端。程式運行效果:
26. 面向UDP的串連
27. 伺服器:socket
a) bind
b) 接收資料:
int recvfrom (
SOCKET s, //通訊端
char FAR* buf, //接收資料
int len, //長度
int flags, //會影響調用行為,0
struct sockaddr FAR* from, //接收發送方的地址資訊
int FAR* fromlen //接收長度
);
c) 關閉closesocket
d) Cleanup
28. UDP伺服器端程式:
#include <WINSOCK2.H>#include <stdio.h>void main(){WORD wVersionRequested;WSADATA wsaData;int err;wVersionRequested = MAKEWORD( 1, 1 );err = WSAStartup( wVersionRequested, &wsaData );if ( err != 0 ) {return;}if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) {WSACleanup( );return; }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(6000);bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));SOCKADDR_IN addrClient;int len=sizeof(SOCKADDR);char recvBuf[100];recvfrom(sockSrv,recvBuf,100,0,(SOCKADDR*)&addrClient,&len);printf("%s\n",recvBuf);closesocket(sockSrv);WSACleanup();}
28. UDP用戶端:
a) socket定義
b) 發送:
int sendto (
SOCKET s,
const char FAR * buf,
int len,
int flags,
const struct sockaddr FAR * to,
int tolen
);
29. UDP用戶端程式
#include <WINSOCK2.H>#include <stdio.h>void main(){WORD wVersionRequested;WSADATA wsaData;int err;wVersionRequested = MAKEWORD( 1, 1 );err = WSAStartup( wVersionRequested, &wsaData );if ( err != 0 ) {return;}if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) {WSACleanup( );return; }SOCKET sockClient=socket(AF_INET,SOCK_DGRAM,0);SOCKADDR_IN addrSrv;addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");addrSrv.sin_family=AF_INET;addrSrv.sin_port=htons(6000);sendto(sockClient,"Hello 劉窪村",strlen("Hello 劉窪村")+1,0,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));closesocket(sockClient);WSACleanup();}運行結果:
30. 注意:每個程式都要加上ws2_32.lib連結庫。如下添加:
By 劉窪村