1. 程式人生 > >基於TCP(面向連線)的socket程式設計

基於TCP(面向連線)的socket程式設計

基於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庫,方法:工程—屬性—連結器—輸入—附加依賴項。

除錯的時候先啟動伺服器,再右鍵客戶端的工程—除錯—啟動新例項。