基於TCP(面向連線)的socket程式設計
阿新 • • 發佈:2018-11-22
基於TCP的socket程式設計是採用的流式套接字(SOCK_STREAM)
伺服器端程式設計的步驟:
1:載入套接字型檔,建立套接字(WSAStartup()/socket());
2:繫結套接字到一個IP地址和一個埠上(bind());
3:將套接字設定為監聽模式等待連線請求(listen());
4:請求到來後,接受連線請求,返回一個新的對應於此次連線的套接字(accept());
5:用返回的套接字和客戶端進行通訊(send()/recv());
6:返回,等待另一連線請求;
7:關閉套接字,關閉載入的套接字型檔(closesocket()/WSACleanup())。
建立一個Win32 Console Application型別的應用程式,進一步選擇空專案。
在原始檔下建立一個空的cpp檔案。
#include<WinSock2.h>
#include<stdio.h>
//支援Windows Sockets 1.1版本
void main()
{
/*載入套接字型檔*/
WORD wVersionRequested;// 所使用套接字的版本號
WSADATA wsaData; // 儲存套接字版本的有關資訊
int err;
wVersionRequested = MAKEWORD( 1, 1); // 請求版本號,高位和低位位元組均為1
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0){ //返回值為0表示成功,不為0則報錯
return;
}
if (LOBYTE(wsaData.wVersion) != 1 ||
HIBYTE(wsaData.wVersion) != 1){
WSACleanup(); //如果高位或低位位元組不為1,即不是我們所請求的版本,則終止對套接字的使用
return;
}
/*建立用於監聽的套接字*/
SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0);// TCP/IP協議的套接字只能是AF_INET,
// 流式套接字,第三個引數設為0則自動選擇合適的協議
/* 繫結套接字 */
SOCKADDR_IN addrSrv;// 伺服器地址資訊,使用SOCKADDR_IN 代替SOCKETADD, 結構體的大小相等,可強制轉換
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //設定地址,將主機位元組順序轉換為網路位元組順序
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(6000); // 指定埠,使用1024以上的埠號,用htons函式轉換為網路位元組序
// 將監聽套接字繫結到本地地址和埠上
bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
//將套接字設為監聽模式,準備接收客戶請求
listen(sockSrv, 5); //等待連線的最大長度設為5
/* 等待客戶到來並接收發送資料 */
SOCKADDR_IN addrClient; // 接收客戶地址資訊緩衝區
int len = sizeof(SOCKADDR);
while (1)
{
// 等待接收客戶連線請求,並返回"連線套接字",利用這個套接字實現通訊
SOCKET sockConn = accept(sockSrv, (SOCKADDR*)&addrClient, &len);
char sendBuf[100];
sprintf_s(sendBuf, "Welcome %s to http://www.sunxin.org", //用sprintf向陣列輸入客戶端的地址
inet_ntoa(addrClient.sin_addr)); //inet_ntoa用於格式化客戶端的地址
// 傳送資料,多加一個長度是字串結束符
send(sockConn, sendBuf, strlen(sendBuf) + 1, 0);
char recvBuf[100];
// 接收資料
recv(sockConn, recvBuf, 100, 0);
//列印接收的資料
printf("%s\n", recvBuf);
//關閉套接字
closesocket(sockConn);
}
}
客戶端程式設計的步驟:
1:載入套接字型檔,建立套接字(WSAStartup()/socket());
2:向伺服器發出連線請求(connect());
3:和伺服器端進行通訊(send()/recv());
4:關閉套接字,關閉載入的套接字型檔(closesocket()/WSACleanup())。
#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(); //如果高位或低位位元組不為1,即不是我們所請求的版本,則終止對套接字的使用
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"); //採用本地迴路地址進行測試
//inet_addr將點分十進位制表示的IP地址轉換為u_long型別
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 gufan", strlen("This is gufan") + 1, 0);
//關閉套接字
closesocket(sockClient);
WSACleanup();
system("pause");
}
此外,還要為兩個工程檔案都新增ws2_32.lib庫,方法:工程—屬性—連結器—輸入—附加依賴項。
除錯的時候先啟動伺服器,再右鍵客戶端的工程—除錯—啟動新例項。