建立一個簡單的VC++ Socket程式
本文主要結合MSDN上關於WinSocket的幾篇官方文件,建立一個簡單的VC++ Socket示例程式,演示一個基本的CS模型。參考連結如下:
一、C/S —— Client和Server
網路程式設計中,最常見的是C/S模型,它有一個(或多個)client和一個server。事實上,我們需要建立兩個不同的socket network應用程式來演示該示例(我們可以將這兩個工程放到一個solution下,具體方法是:先建立一個工程,然後修改名字,再在該solution下新增另一個工程)。這兩個應用程式——client和server有不同的行為,如下:
Server
- Initialize Winsock.
- Create a socket.
- Bind the socket.
- Listen on the socket for a client.
- Accept a connection from a client.
- Receive and send data.
- Disconnect.
Client
- Initialize Winsock.
- Create a socket.
- Connect to the server.
- Send and receive data.
- Disconnect.
二、標頭檔案和庫
分別為client和server新建兩個普通的我win32 console程式,包含下面的標頭檔案和庫:
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#pragma comment(lib, "Ws2_32.lib")
其中,”stdio.h“用於標準輸入輸出,如:printf()函式。需要注意的是,”winsock2.h“,官方解釋:點選開啟連結
The Winsock2.h header
file internally includes core elements from the Windows.h header
file, so there is not usually an #include line for the
注意,要帶上數字”2“。
三、client程式碼
#include <stdio.h>
#include <Winsock2.h>
#include <iostream>
#include <fstream>
using namespace std;
#pragma comment(lib,"WS2_32.lib") // Winsocket是動態連結庫,需要載入它的庫和包含對應的標頭檔案
char recvBuf[1310721];
int _tmain(int argc, _TCHAR* argv[])
{
WSADATA wsd;
SOCKET sockClient; //客戶端socket
SOCKADDR_IN addrSrv;
//char recvBuf[1310721];
memset(recvBuf, 0, 1310721);
if(WSAStartup(MAKEWORD(2,2),&wsd)!=0) // 1> 初始化Windows的socket庫(API集)
{
printf("start up failed!\n");
return 0;
}
sockClient=socket(AF_INET,SOCK_STREAM,0); // 2> 建立socket
if (INVALID_SOCKET == sockClient)
{
printf("create client socket error!\n");
return 0;
}
addrSrv.sin_addr.S_un.S_addr=inet_addr("192.168.18.129");
addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons(6000);
if (SOCKET_ERROR == connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR))) //連線伺服器端
{
printf("connect server error!\n");
return 0;
}
ofstream ofs("recv.txt");
while (1)
{
printf("wait for recv data\n");
int recvNum = recv(sockClient,recvBuf,1310721,0); //接收伺服器端資料
if (recvNum == 1310721 - 1)
{
printf("%s\n",recvBuf);
ofs.write("******* ", strlen("******* "));
ofs.write(recvBuf, recvNum);
ofs.write("\n\n", strlen("\n\n"));
ofs.flush();
}
Sleep(1000);
}
ofs.flush();
ofs.close();
//send(sockClient,"hello world",strlen("hello world")+1,0); //向伺服器端傳送資料
closesocket(sockClient); //關閉連線
WSACleanup();
return 0;
}
三、server程式碼
#include <stdio.h>
#include <Winsock2.h>
#include <iostream>
#include <fstream>
using namespace std;
#pragma comment(lib,"WS2_32.lib")
char sendBuf[1310721];
int _tmain(int argc, _TCHAR* argv[])
{
WSADATA wsd;
SOCKET server; //伺服器socket
SOCKADDR_IN addrSrv;
//char sendBuf[1310721];
//memset(&sendBuf[0], '3', 1310721);
memset(&sendBuf[0], '9', 100000);
memset(&sendBuf[100000], '0', 100000);
memset(&sendBuf[200000], '4', 100000);
memset(&sendBuf[300000], '1', 100000);
memset(&sendBuf[400000], '8', 100000);
memset(&sendBuf[500000], '5', 100000);
memset(&sendBuf[600000], '2', 100000);
memset(&sendBuf[700000], '6', 100000);
memset(&sendBuf[800000], '3', 100000);
memset(&sendBuf[900000], '7', 100000);
memset(&sendBuf[1000000], '5', 310721);
sendBuf[1310721 - 1] = '\0';
SOCKADDR_IN addrClient;
SOCKET client; //連線的客戶端socket
int len;
if(WSAStartup(MAKEWORD(2,2),&wsd)!=0) // 1> 初始化Windows的socket庫(API集)
{
printf("start up failed!\n");
return 0 ;
}
server = socket(AF_INET,SOCK_STREAM,0);
if (INVALID_SOCKET == server) // 2> 建立socket
{
printf("create server socket error!\n");
return 0;
}
addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY); //設定地址
addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons(6000); //設定埠號
if (SOCKET_ERROR == bind(server,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR))) // 3> 將一個socket與一個應用程式(IP + PORT_NUMBER)繫結
{
printf("bind error!\n");
return 0;
}
if (SOCKET_ERROR == listen(server,5)) // 4> 設定該socket為監聽模式,設定最多連線數
{
printf("listen error!\n");
return 0;
}
len=sizeof(SOCKADDR);
printf("wait for accept client\n");
client = accept(server,(SOCKADDR*)&addrClient,&len); // 5> 監聽到請求後,接受請求,並返回對應於此處連線的套接字
if (INVALID_SOCKET != client)
{
printf("Welcome %s \n", inet_ntoa(addrClient.sin_addr));
}
ofstream ofs("send.txt");
while(1)
{
int sendNum = send(client,sendBuf,strlen(sendBuf),0); // 6> 用返回的套接字和客戶端通訊,傳送資訊給客戶端
if (sendNum == strlen(sendBuf))
{
//recv(client,recvBuf,100,0); // 6> 用返回的套接字和客戶端通訊,接收客戶端資料
printf("%s\n",sendBuf);
ofs.write("******* ", strlen("******* "));
ofs.write(sendBuf, sendNum);
ofs.write("\n\n", strlen("\n\n"));
ofs.flush();
}
Sleep(1000);
}
ofs.flush();
ofs.close();
closesocket(client); //關閉連線
WSACleanup();
return 0;
}