C++基於Socket的TCP網絡編程(IPv4)

TCP的服務端程序:

// StudyC++Sokcet.cpp : 此文件包含 "main" 函數。程序執行將在此處開始並結束。
//

#include <iostream>
#include<winsock2.h>//winsock2.0的頭文件,鏈接windows的動態庫
using namespace std;//命名空間

//指定動態庫的lib文件
#pragma comment(lib,"ws2_32.lib")

//TCP服務端
int main()
{
    ////////////////////////////////////////////////////////////////////////
    
    //初始化winsock2.2相關的動態庫
    WSADATA wd;//獲取Socket相關信息
    if (WSAStartup(MAKEWORD(2,2),&wd)!=0)//0標識成功 MAKEWORD版本
    {
        cout << "WSAStartup error:"<< WSAGetLastError() <<endl;//WSAGetLastError()獲取錯誤
    }
    //////////////////////////////////////////////////////
    //TCP Server的代碼結構
    //1.創建TCP socket 流式套接字
    SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//地址族,套接字類型,協議----成功返回一個socket
    if (s == INVALID_SOCKET)//創建失敗,返回錯誤信息
    {
        cout << "socket error:" << WSAGetLastError() << endl;
        return 0;
    }

    //2.綁定socket到一個IP地址和端口
    //sockaddr addr;//地址
    sockaddr_in addr;//sockaddr變種
    addr.sin_port = htons(8000);//網絡字節序,端口號
    addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//ip地址
    addr.sin_family = AF_INET;//地址族
    int len = sizeof(sockaddr_in);//指定大小
    if (bind(s, (sockaddr*)&addr, len) == SOCKET_ERROR)//(sockaddr*)強制轉換
    {
        //有時socket端口被佔用了,也沒辦法bind就會返回錯誤
        cout << "bind error:" << WSAGetLastError() << endl;
        return 0;
    }
    //3.監聽
    //s套接字,5也可用一個宏,表示正在等待完成相應TCP三路握手過程的隊列長度
    if(listen(s, 5) == SOCKET_ERROR)
    {
        cout << "listen error:" << WSAGetLastError() << endl;
        return 0;
    }

    //4.接受客戶端請求,並且返回和客戶端通訊的套接字
    sockaddr_in addrClient;//保存客戶端IP地址端口:客戶端地址是獲得的,不是指定的,所以要註釋下面的地址
    //addr.sin_port = htons(8000);//網絡字節序,端口號
    //addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//ip地址
    //addr.sin_family = AF_INET;//地址族
    memset(&addrClient, 0, sizeof(sockaddr_in));//置空
    int lenClient = sizeof(addrClient);
    SOCKET c = accept(s,(sockaddr*)&addrClient,&lenClient);//成功返回clinet端的套接字
    if (c == INVALID_SOCKET)
    {
        cout << "accept error" << WSAGetLastError() << endl;
        return 0;
    }

    //5.發送、接收消息
    int ret = 0;
    do
    {   //向客戶端發送數據,不能用監聽套接字,要用返回套接字
        ret = send(c,"I am Server!",strlen("I am Server!"),0);//把flag置0

        //接收客戶端的消息
        char buf[64] = {"\0"};//初始化以免亂碼
        ret = recv(c,buf,64,0);//把flag置0
        cout << "recv:"<<inet_ntoa(addrClient.sin_addr)<< " : "<< buf << endl;//inet_ntoa轉化爲IP字符串
    } while (ret != SOCKET_ERROR && ret != 0);//成功返回接收到的字節數,錯誤返回SOCKET_ERROR,
    //對方關閉連接返回0,否則認爲對方一直髮送,我方循環接收
    //清理winsock環境

    //6.關閉套接字
    closesocket(s);
    ///////////////////////////////////////////////////////////////////////
    WSACleanup();
    return 0;
    ///////////////////////////////////////////////////////////////////////
}

TCP客戶端程序:

// TCP_Clinet.cpp : 此文件包含 "main" 函數。程序執行將在此處開始並結束。
//

#include <iostream>
#include<winsock2.h>//winsock2.0的頭文件,鏈接windows的動態庫
using namespace std;//命名空間

//指定動態庫的lib文件
#pragma comment(lib,"ws2_32.lib")

//TCP客戶端
int main()
{
    ////////////////////////////////////////////////////////////////////////

    //初始化winsock2.2相關的動態庫
    WSADATA wd;//獲取Socket相關信息
    if (WSAStartup(MAKEWORD(2, 2), &wd) != 0)//0標識成功 MAKEWORD版本
    {
        cout << "WSAStartup error:" << WSAGetLastError() << endl;//WSAGetLastError()獲取錯誤
    }

    //////////////////////////////////////////////////////
    //TCP Clinet的代碼結構
    //1.創建TCP socket 流式套接字
    SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//地址族,套接字類型,協議----成功返回一個socket
    if (s == INVALID_SOCKET)//創建失敗,返回錯誤信息
    {
        cout << "socket error:" << WSAGetLastError() << endl;
        return 0;
    }

    //2.鏈接服務端
    sockaddr_in addr;//sockaddr變種
    addr.sin_port = htons(8000);//網絡字節序,端口號
    addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//ip地址
    addr.sin_family = AF_INET;//地址族
    int len = sizeof(sockaddr_in);//指定大小
    if (connect(s, (sockaddr*)&addr, len) == SOCKET_ERROR)
    {
        cout << "connect error:" << WSAGetLastError() << endl;
        return 0;
    }

    //3.接收發送消息
    int ret = 0;
    do
    {
        //接收客戶端的消息
        char buf[64] = {"\0"};
        ret = recv(s,buf,64,0);//把flag置0
        cout << "recv" << inet_ntoa(addr.sin_addr) << ":  " << buf << endl;//inet_ntoa
        //發送
        ret = send(s, "i am Client!", strlen("i am Client!"),0);
        Sleep(1000);
    } while (ret != SOCKET_ERROR && ret != 0);

    //4.關閉套接字
    closesocket(s);
    ///////////////////////////////////////////////////////////////////////
    WSACleanup();
    return 0;
    ///////////////////////////////////////////////////////////////////////

}

運行,先點開工程下面的Server.exe,再點開Clinet.exe

完整程序連接:https://download.csdn.net/download/qq_40155090/12423186 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章