Winsock网络编程

简介

winsock就是在Windows下的网络套接字编程,现在使用的是Windows Socket 2,是专门为C/C++编程而设计的。
Microsoft给出了使用winsock的教程Microsoft winsock

客户端和服务器端

以TCP为例,客户端需要做的事情有
(1)WSAStartup初始化Winsock API
(2)getaddrinfo
(3)Create Socket
(4)Connect
到这里就完成连接,然后就能用send函数和recv函数来进行发送和接受
(5)shutdown关闭连接

服务器端要做的事情如下
(1)WSAStartup初始化Winsock API
(2)getaddrinfo
(3)Create Socket
(4)Bind
把套接字和网络端口号绑定
(5)Listen
监听端口号
(6)Accept
当有客户端发送Connect请求之后,服务器端才会Accept,Accept之后就能与客户端之间通过send和recv函数进行发送和接受
(7)shutdown关闭连接

实现

我把客户端和服务器端的Socket写到一个类里面,要实现什么样的功能只需要在外部调用即可。
头文件

#include 
#include 
#include 
#pragma comment(lib, "Ws2_32.lib")

#define LEN 512

using namespace std;

class Socket
{
public:
    //func
    Socket();
    void TCPSocketS(char* port);
    void TCPSocketC(char* addr, char* port);

    //common
    void myInit();
    void myGetaddrinfo(char* socktype, char* protocol, char* addr, char* port);

    //difference
    void myRecvC();
    void mySendC();
    void mySocketC();
    void shutdownC();
    void myRecvS();
    void mySendS();
    void mySocketS();
    void shutdownS();

    //server
    void myBind();
    void myListen();
    void myAccept();

    //client
    void myConnect();

private:
    WSADATA wsaData;
    struct addrinfo *result, hints;
    SOCKET ClientSocket, ListenSocket, ConnectSocket;
    char recvbuf[LEN];
    char sendbuf[LEN];
};

cpp文件

#include "Socket.h"
#include 
#include 
using namespace std;

Socket::Socket()
{
    //initial
    result = NULL;

}

void Socket::myInit()
{
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    {
        printf("WSAStartup failed\n");
    }
    else
    {
        printf("WSAStartup success\n");
    }
}

void Socket::myGetaddrinfo(char* role, char* protocol,
    char* addr, char* port)
{
    //
    ZeroMemory(&hints, sizeof(hints));

    hints.ai_family = AF_INET;
    if (protocol == "TCP")
    //if (strcmp(protocol, "TCP") == 0)
    {
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_protocol = IPPROTO_TCP;
    }
    else if (strcmp(protocol, "UDP") == 0)
    {
        hints.ai_socktype = SOCK_DGRAM;
        hints.ai_protocol = IPPROTO_UDP;
    }
    else
    {
        printf("getaddrinfo protocol fail\n");
    }

    if (strcmp(role, "Server") == 0)
    {
        hints.ai_flags = AI_PASSIVE;
    }

    //getaddrinfo
    if (getaddrinfo(addr, port, &hints, &result) != 0)
    {
        printf("getaddrinfo failed\n");
    }
    else
    {
        printf("getaddrinfo success\n");
    }
}

void Socket::myRecvS()
{
    int iResult;
    iResult = recv(ClientSocket, recvbuf, LEN, 0);
    if (iResult > 0)
    {
        printf("Bytes received: %d\n", iResult);
        recvbuf[iResult] = '\0';
        printf("string is %s\n", recvbuf);
    }
    else if (iResult == 0)
        printf("Connection closed\n");
    else
    {
        printf("recv failed: %d\n", WSAGetLastError());
    }
}

void Socket::myRecvC()
{
    int iResult;
    iResult = recv(ConnectSocket, recvbuf, LEN, 0);
    if (iResult > 0)
    {
        printf("Bytes received: %d\n", iResult);
        recvbuf[iResult] = '\0';
        printf("string is %s\n", recvbuf);
    }
    else if (iResult == 0)
        printf("Connection closed\n");
    else
    {
        printf("recv failed: %d\n", WSAGetLastError());
    }
}

void Socket::mySendC()
{
    printf("Input: ");
    scanf("%s", sendbuf);

    int iResult;
    iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0);
    if (iResult == SOCKET_ERROR)
    {
        printf("send failed\n");
        closesocket(ConnectSocket);
        WSACleanup();
    }
}

void Socket::mySendS()
{
    printf("Input: ");
    scanf("%s", sendbuf);

    int iResult;
    iResult = send(ClientSocket, sendbuf, (int)strlen(sendbuf), 0);
    if (iResult == SOCKET_ERROR)
    {
        printf("send failed\n");
        closesocket(ClientSocket);
        WSACleanup();
    }
}

void Socket::mySocketC()
{
    ConnectSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
}

void Socket::mySocketS()
{
    ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
}

void Socket::shutdownC()
{
    if (shutdown(ConnectSocket, SD_SEND) == SOCKET_ERROR)
    {
        printf("shutdown failed: %d\n", WSAGetLastError());
    }
    closesocket(ConnectSocket);
    WSACleanup();
}

void Socket::shutdownS()
{
    if (shutdown(ClientSocket, SD_SEND) == SOCKET_ERROR)
    {
        printf("shuwdown failed: %d\n", WSAGetLastError());
    }
    closesocket(ClientSocket);
    WSACleanup();
}


//Server func
void Socket::myBind()
{
    if (bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen) == SOCKET_ERROR)
    {
        printf("bind failed\n");
        closesocket(ListenSocket);
        WSACleanup();
    }
    else
    {
        printf("bind success\n");
    }
    freeaddrinfo(result);
}

void Socket::myListen()
{
    if (listen(ListenSocket, SOMAXCONN) == SOCKET_ERROR)
    {
        printf("listen fail\n");
        closesocket(ListenSocket);
        WSACleanup();
    }
    else
    {
        printf("listen success\n");
    }
}

void Socket::myAccept()
{
    ClientSocket = accept(ListenSocket, NULL, NULL);
    if (ClientSocket == INVALID_SOCKET)
    {
        printf("accept fail\n");
        closesocket(ListenSocket);
        WSACleanup();
    }
    else
    {
        printf("accept success\n");
    }
}

//Client func
void Socket::myConnect()
{
    if (connect(ConnectSocket, result->ai_addr, (int)result->ai_addrlen) == SOCKET_ERROR)
    {
        printf("connect error\n");
        closesocket(ConnectSocket);
        ConnectSocket = INVALID_SOCKET;
    }
    freeaddrinfo(result);
    if (ConnectSocket == INVALID_SOCKET)
    {
        printf("Unable to connect to server\n");
        WSACleanup();
    }
}



//packet func
void Socket::TCPSocketS(char* port)
{
    myInit();
    myGetaddrinfo("Server", "TCP", NULL, port);
    mySocketS();
    myBind();
    myListen();
    while (true)
    {
        myAccept();
        myRecvS();
    }
}


void Socket::TCPSocketC(char* addr, char* port)
{
    myInit();
    myGetaddrinfo("Client", "TCP", addr, port);
    mySocketC();
    myConnect();
    mySendC();
    shutdownC();
}

主函数调用只需要几行技能完成客户端和服务器端的配置和使用

客户端

#include "Socket.h"

#define port "8889"
#define addr "127.0.0.1"
#define addr2 NULL

int main()
{
    Socket a;
    while (true)
    { 
        a.TCPSocketC(addr, port);
    }
    return 1;
}

服务器端

#include "Socket.h"
#define port "8889"
#define addr "127.0.0.1"
#define addr2 NULL

int main()
{
    Socket a;
    a.TCPSocketS(port);
    return 1;
}

效果图如下
Winsock网络编程_第1张图片

比较基础的winsock编程,自己写的代码,可能有些小bug没发现~

你可能感兴趣的:(其他)