創建一個能夠不停地接收客戶端新的鏈接,但不能處理複雜的業務的C/S網絡程序

在Windows平臺上主要有兩個版本的Socket Api函數:
WinSock 1.1和WinSock 2.2 , 2.2版本默認兼容1.1版本,
1.1 winsock.h wsock32.lib winsock.dll
2.2 winsock2.h ws2 32.lib ws2 32.dllios

2.0版本的Socket比1.1的多一些高級的功能如:
多重協議支持:經過SPI接口支持其餘協議;
多重命名空間:根據服務與主機名選擇協議
重疊10模式:加強10吞吐量與提升性能
分散與聚合:從多個緩衝區發送與接收數據
有條件接受:有選擇性地決定是否接受鏈接;
套接字共享:多個進程共享一個套接字句柄。編程

Socket套接字類型:
比較經常使用的包括:流式套接字(使用TCP) ,數據報套接字(使用UDP) ,原始套接字等
TCP與UDP各有優缺點:
TCP :面向鏈接、穩定、須要資源多;
UDP :面向無鏈接(通常狀況下)、不穩定、須要資源少。
用手機打電話時面向鏈接的,用手機發短信是面向無鏈接的,目前來講網絡上比較經常使用的是TCP類型的衰接字。安全

TCP與UDP的區別:
1.基於鏈接與無鏈接
2.對系統資源的要求(TCP較多,UDP少)
3.UDP程序結構較簡單
4.流模式(TCP)與數據報模式(UDP)
   TCP保證數據正確性, UDP可能丟包 
   TCP保證數據順序, UDP不保證服務器

具體編程時的區別
1. socket0的參數不一樣
2. UDP Server不須要淘用listen和accept
3. UDP收發數據用sendto/recvfrom函數
4. TCP:地址信息在connect/accept時肯定
    UDP :在sendto/recvfrom函數中每次均需指定地址信息
5. UDP : shutdown函數無效網絡

部分知足如下幾點要求時,應該採用UDP面向數據報方式
1.網絡數據大多爲短消息
2.擁有大量Client
3.對數據安全性無特殊要求
4.網絡負擔很是重,但對響應速度要求高socket

TCP類型Socket程序開發流程:
TCP服務端: WSASartup, socket, bind, listen, accept, read, write, closesocket, WSACleanup.
TCP客戶端: WSASartup, socket, connect, read, write, closesocket, WSACleanup.函數

流程圖:性能

這種結構雖然能不停地接收客戶端新的鏈接,但不能處理複雜的業務。spa

服務器端:code

#include<WinSock2.h>
#include<Windows.h>
#include<stdio.h>
#include<iostream>

#pragma comment(lib,"ws2_32.lib")

int main()
{
    WORD ver = MAKEWORD(2, 2);
    WSADATA dat;
    //WinSocket啓動
    WSAStartup(ver, &dat);

    //創建一個socket
    SOCKET _sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //AF_INET建立一個IPV4的套接字,SOCK_STREAM面向數據流的,IPPROTO_TCP TCP
    if (INVALID_SOCKET == _sock)
    {
        printf("ERROR:創建失敗!\n");
    }
    //1.綁定
    sockaddr_in _sin = {};     //建立網絡地址
    _sin.sin_family = AF_INET;
    _sin.sin_port = htons(4567); //Host to Network Short
    _sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); // IP地址 
    if (bind(_sock, (sockaddr *)&_sin, sizeof(_sin)) == SOCKET_ERROR)
    {
        printf("ERROR:綁定失敗!\n");
    }
    else
    {
        printf("TRUE:綁定成功!\n");
    }
    //2.監聽網絡端口
    if (listen(_sock, 5) == SOCKET_ERROR)//第二個參數爲最大等待多少人能夠同時鏈接
    {
        printf("ERROR:監聽失敗!\n");
    }
    else
    {
        printf("TRUE:監聽成功!\n");
    }
    //3.等待接收客戶端鏈接
    sockaddr_in clientAddr = {};
    int nAddrLen = sizeof(sockaddr_in);
    SOCKET _cSOCK = INVALID_SOCKET;
    char msgBuff[] = "Hello,My is Server!\n";
    while (1)
    {
        _cSOCK = accept(_sock, (sockaddr *)&clientAddr, &nAddrLen);
        if (_cSOCK == INVALID_SOCKET)
        {
            printf("ERROR:無效客戶端SOCKET!\n");
        }
        printf("新客戶端加入:IP = %s\n", inet_ntoa(clientAddr.sin_addr));//inet_ntoa(clientAddr.sin_addr)將接收到的IP地址轉化爲字符串
        //向客戶端發送一條數據
        send(_cSOCK, msgBuff, strlen(msgBuff) + 1, 0);
    }

    //5,關閉自身的socket
    closesocket(_sock);


    //WinSocket關閉
    WSACleanup();

    system("pause");
    return 0;
}

 

客戶端:

 

 

#include<WinSock2.h>
#include<Windows.h>
#include<stdio.h>

#pragma comment(lib,"ws2_32.lib")

int main()
{
    WORD ver = MAKEWORD(2, 2);
    WSADATA dat;
    WSAStartup(ver, &dat);

    //創建一個socket
    SOCKET _sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (INVALID_SOCKET == _sock)
    {
        printf("ERROR:創建失敗!\n");
    }
    //鏈接服務器
    sockaddr_in _sin = {};     //建立網絡地址
    _sin.sin_family = AF_INET;
    _sin.sin_port = htons(4567); //Host to Network Short
    _sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//inet_addr("127.0.0.1"); // IP地址 
    int ret = connect(_sock, (sockaddr *)&_sin, sizeof(sockaddr_in));
    if (SOCKET_ERROR == ret)
    {
        printf("ERROR:鏈接失敗!\n");
    }
    else
    {
        printf("鏈接成功!\n");
    }
    //接收服務器信息
    char recvBuff[256] = {};
    int nlen = recv(_sock, recvBuff, 256, 0);
    if (nlen <= 0)
    {
        printf("ERROR:接收失敗!\n");
    }
    else
    {
        printf("接收到數據:%s\n", recvBuff);
    }
    //關閉套接字
    closesocket(_sock);

    //WinSocket啓動
    WSAStartup(ver, &dat);



    //WinSocket關閉
    WSACleanup();

    getchar();
    return 0;
}
相關文章
相關標籤/搜索