建立一个可以不停地接收客户端新的连接,但不能处理复杂的业务的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.dll

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.网络负担非常重,但对响应速度要求高

TCP类型Socket程序开发流程:
TCP服务端: WSASartup, socket, bind, listen, accept, read, write, closesocket, WSACleanup.
TCP客户端: WSASartup, socket, connect, read, write, closesocket, WSACleanup.

流程图:

这种结构虽然能不停地接收客户端新的连接,但不能处理复杂的业务。

服务器端:

#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;
}

 

posted @ 2019-05-21 17:44  追风的小蚂蚁  阅读(261)  评论(0编辑  收藏  举报