Windows socket网络编程-TCP通信

步骤如下:

服务器:

1.初始化

包含Winsock2.h头文件和引用ws2_32.lib静态库。
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")   

WSAStartUp函数

2.创建侦听套接字

socket

3.绑定ip和端口,绑定侦听套接字

SOCKADDR_IN

bind

4.开启监听

listen

5.等待客户端连接

accept

6.收发数据

recv/send

客户端:

1.初始化

包含Winsock2.h头文件和引用ws2_32.lib静态库。
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")   

WSAStartUp函数

2.创建连接套接字

socket

3.地址解析并连接服务器

SOCKADDR_IN

connect

4.收发数据

recv/send

-------------------------Code----------------------------------------

服务器代码如下:

#include "stdafx.h"
#include <WinSock2.h>
#include <WS2tcpip.h> 
#pragma comment(lib,"ws2_32.lib")   
#include <stdio.h> 

int main()  
{  
    /// 初始化socket  
    WSADATA wsaData;  
    WORD version = MAKEWORD(2,2);  
    int result = 0;  
    result = WSAStartup(version, &wsaData);  
    if (0 != result)  
    {  
        std::cout << "WSAStartup() error." << std::endl;  
        return -1;  
    }  
  
    /// 创建侦听socket   
    SOCKET socketListen;  
    socketListen = socket(AF_INET, SOCK_STREAM, 0);  
    if (socketListen == INVALID_SOCKET)  
    {  
        WSACleanup();  
        std::cout << "socket() error." << std::endl;  
        return -1;  
    }  
  
    /// 服务器地址结构   
    sockaddr_in svrAddress;  
    svrAddress.sin_family = AF_INET;  
    svrAddress.sin_addr.s_addr = INADDR_ANY;  
    svrAddress.sin_port = htons(8000);  
  
    /// 绑定服务器套接字   
    result = bind(socketListen, (sockaddr*)&svrAddress, sizeof(svrAddress));  
    if (result == SOCKET_ERROR)  
    {  
        closesocket(socketListen);  
        WSACleanup();  
        std::cout << "bind() error." << std::endl;  
        return -1;  
    }  
  
    /// 开启监听  
    result = listen(socketListen, 5);  
    if (result == SOCKET_ERROR)  
    {  
        closesocket(socketListen);  
        WSACleanup();  
        std::cout << "listen() error." << std::endl;  
        return -1;  
    }  
    std::cout << "服务器启动成功,监听端口:" << ntohs(svrAddress.sin_port) << std::endl;  
  
    /// select模型   
    fd_set allSockSet;   
    FD_ZERO(&allSockSet);   
  
    FD_SET(socketListen, &allSockSet); // 将socketListen加入套接字集合中   
  
    while (true)  
    {  
        fd_set readSet;  
        FD_ZERO(&readSet);                    //初始化可读队列
        readSet = allSockSet;   
          
        result = select(0, &readSet, NULL, NULL, NULL);  
        if (result == SOCKET_ERROR)  
        {  
            std::cout << "select() error." << std::endl;  
            break;  
        }  
  
        if (FD_ISSET(socketListen, &readSet))  
        {  
            sockaddr_in clientAddr;  
            int len = sizeof(clientAddr);  
        
            SOCKET clientSocket = accept(socketListen, (sockaddr*)&clientAddr, &len);         
            if (clientSocket == INVALID_SOCKET)  
            {  
                std::cout << "accept() error." << std::endl;  
                break;  
            }  
            FD_SET(clientSocket, &allSockSet);   /// 将新创建的套接字加入到集合中   
  
            char ipAddress[16] = { 0 };  
            inet_ntop(AF_INET, &clientAddr, ipAddress, 16);  
            std::cout << "有新的连接[" << ipAddress << ":" << ntohs(clientAddr.sin_port)  
                << "], 目前客户端的数量为:" << allSockSet.fd_count - 1 << std::endl;       //去掉一个侦听套接字
  
            continue;  
        }  

        for (u_int i = 0; i < allSockSet.fd_count; ++i)  
        {  
            SOCKET socket = allSockSet.fd_array[i];  
  
            sockaddr_in clientAddr;  
            int len = sizeof(clientAddr);  
            getpeername(socket, (struct sockaddr *)&clientAddr, &len);      //获得与套接口相连的远程协议地址
            char ipAddress[16] = { 0 };  
            inet_ntop(AF_INET, &clientAddr, ipAddress, 16);  
  
            /// 可读性监视,可读性指有连接到来、有数据到来、连接已关闭、重置或终止  
            if (FD_ISSET(socket, &readSet))  
            {  
                char bufRecv[100];  
                result = recv(socket, bufRecv, 100, 0);  
                if (result == SOCKET_ERROR)  
                {  
                    DWORD err = WSAGetLastError();  
                    if (err == WSAECONNRESET)       /// 客户端的socket没有被正常关闭,即没有调用closesocket  
                    {  
                        std::cout << "客户端[" << ipAddress << ":" << ntohs(clientAddr.sin_port) << "]被强行关闭, ";  
                    }  
                    else  
                    {  
                        std::cout << "recv() error," << std::endl;  
                    }  
          
                    closesocket(socket);  
                    FD_CLR(socket, &allSockSet);  
  
                    std::cout << "目前客户端的数量为:" << allSockSet.fd_count - 1 << std::endl;  
                    break;  
                }  
                else if (result == 0)               /// 客户端的socket调用closesocket正常关闭  
                {  
                    closesocket(socket);  
                    FD_CLR(socket, &allSockSet);  
  
                    std::cout << "客户端[" << ipAddress << ":" << ntohs(clientAddr.sin_port)   
                        << "]已经退出,目前客户端的数量为:" << allSockSet.fd_count - 1 << std::endl;  
                    break;  
                }  
  
                bufRecv[result] = '\0';  
                std::cout << "来自客户端[" << ipAddress << ":" << ntohs(clientAddr.sin_port)  
                    << "]的消息:" << bufRecv << std::endl;  
                
                char szSend[256] = "朕已经收到,你可以滚了!";
                send(socket, szSend, strlen(szSend), 0);
            }  
        }  
    }  
  
    for (u_int i = 0; i < allSockSet.fd_count; ++i)  
    {  
        SOCKET socket = allSockSet.fd_array[i];  
        closesocket(socket);  
    }  
  
    WSACleanup();  
    return 0;  

客户端代码:


#include "stdafx.h"
#include <iostream>  
#include <WS2tcpip.h>  
#include <WinSock2.H>  
using namespace std;
#pragma comment(lib, "ws2_32.lib")  

#define SERVER_ADDRESS      "192.168.1.179"  
#define SERVER_PORT         8000  

#define SOCKET_NUM          120       /// 客户端socket的个数,修改该值可以改变连接到服务器的客户端个数  

SOCKET socketClient;

char g_szBuf[512] = "";

HANDLE hMutex;

void Input();

void Recv();

DWORD WINAPI ThreadProc(
    _In_ LPVOID lpParameter
    );

DWORD WINAPI SendDataThreadProc(
    _In_ LPVOID lpParameter
    );

int main()  
{  
    WORD wVersionRequested = MAKEWORD(2, 2);  
    WSADATA wsaData;  
    int err = WSAStartup(wVersionRequested, &wsaData);  
    if (err != 0) return 1;  

    if (LOBYTE(wsaData.wVersion) != 2 ||  
        HIBYTE(wsaData.wVersion) != 2)   
    {  
        WSACleanup();  
        std::cout << "WSAStartup() error." << std::endl;  
        return -1;  
    }    

    socketClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);  
    if (socketClient == INVALID_SOCKET)  
    {  
        WSACleanup();  
        std::cout << "socket() error." << std::endl;  
        return -1;  
    }  


    SOCKADDR_IN server;  
    memset(&server, 0, sizeof(SOCKADDR_IN));  
    server.sin_family = AF_INET;  
    server.sin_port = htons(SERVER_PORT);  
    inet_pton(server.sin_family, SERVER_ADDRESS, &server.sin_addr);  

    err = connect(socketClient, (struct sockaddr *)&server, sizeof(SOCKADDR_IN));  
    if (err == SOCKET_ERROR)  
    {  
        std::cout << "connect() error." << std::endl;  
        closesocket(socketClient);  
        WSACleanup();  
        return -1;  
    }  

    hMutex = CreateMutex(NULL, false, (LPCWSTR)"MutexOne");
    if (NULL == hMutex)
    {
        printf("创建互斥对象失败!\n");
        return -1;
    }

    DWORD dwThreadId = 0;

    /*HANDLE hThread = CreateThread(NULL, NULL, &SendDataThreadProc, NULL, 0, &dwThreadId);
    if (NULL == hThread)
    {
    printf("创建发送线程失败!\n");
    return -1;
    }*/


    HANDLE hThread2 = CreateThread(NULL, NULL, &ThreadProc, NULL, 0, &dwThreadId);
    if (NULL == hThread2)
    {
        printf("创建接收线程失败!\n");
        return -1;
    }


    Input();
//    Recv();
    
    closesocket(socketClient);
    WSACleanup();  

    return 0;  
}  

void Input()
{
    while (true)
    {
        WaitForSingleObject(hMutex, INFINITE);
        char szInput[256] = "";
        printf("Me:");
        scanf("%s", szInput);
        if (strcmp(szInput, "exit") == 0)
        {
            break;
        }
        else
        {
            send(socketClient, szInput, strlen(szInput), 0);
        }
//        printf("\n");
        ReleaseMutex(hMutex);
        
    }
}

void Recv()
{
    while (true)
    {
        
        recv(socketClient, g_szBuf, sizeof(g_szBuf), 0);
        printf("Me Recv Form Server:%s\n", g_szBuf);

        
    }
}

DWORD WINAPI ThreadProc(_In_ LPVOID lpParameter)
{
    
    while (true)
    {
        WaitForSingleObject(hMutex, INFINITE);
        recv(socketClient, g_szBuf, sizeof(g_szBuf), 0);
        printf("Recv Form Server:%s\n\n", g_szBuf);
        ReleaseMutex(hMutex);
    }

    return 0;
}

DWORD WINAPI SendDataThreadProc(_In_ LPVOID lpParameter)
{
    
    while (true)
    {
        WaitForSingleObject(hMutex, INFINITE);
        char szInput[256] = "";
        printf("Me:");
        scanf("%s", szInput);
        if (strcmp(szInput, "exit") == 0)
        {
            break;
        }
        else
        {
            
            send(socketClient, szInput, strlen(szInput), 0);
            
        }
        printf("\n");
        ReleaseMutex(hMutex);
    }
    

    return 0;
}

猜你喜欢

转载自my.oschina.net/andyzzh1314/blog/1816790