IO复用模型的TCP并发服务器

多并发服务器实验

目录

多并发服务器实验

实验内容

大致思路

结果截图

完整源代码


实验设备:   

目标系统:Windows

软件工具:vs2022/vc6/dev

实验要求:

  1. 用select完成使用IO复用模型的TCP并发服务器设计;
  2. 用多线程完成TCP并发服务器设计。

实验内容:

大致思路

  1. 通讯建立后首先由服务器端发送消息,客户端接收消息;接着客户端发送消息,服务器端接收消息,实现交互发送消息。
  2. 服务器同时可以和 多个客户端建立连接,进行交互;用建立连接时服务器端接收的客户端套接字来唯一标识该客户端。服务器端可以随时接收客户端的连接并与其进行交互。
  3. 在某次交互中,服务器端或某客户端有一方发送"end"即终止服务器与其的通信;服务器还可以继续接收其他客户端的请求,与其他客户端通信。

服务器端

  1. 初始化winsock2.DLL

     2、创建套接字

     3、绑定端口和IP

     4、将套接字设为监听状态

     5、主线程循环接收客户端的连接

    6、线程通讯部分

1)、与客户端通讯,先发送再接收数据

2)、接收客户端数据

客户端

1、初始化winsock2.DLL

2、创建套接字

3、连接服务器

4、实现交互部分,客户端先接收后发送数据

1)、接收服务端消息

2)、发送信息给服务器

结果截图

 

 

 

 

完整源代码

服务器端代码:

#include <WinSock2.h>

#include <ws2tcpip.h>

#include <iostream>

using namespace std;

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

#include<windows.h>

#define PORT 65432

DWORD WINAPI ThreadFun(LPVOID lpThreadParameter);

int main()

{

    //初始化winsock2.DLL

    WSADATA wsaData;

    WORD wVersionRequested = MAKEWORD(2, 2);

    if (WSAStartup(wVersionRequested, &wsaData) != 0)

    {

        cout << "加载winsock.dll失败!" << endl;

        return 0;

    }

    //创建套接字

    SOCKET  sock_server;

    if ((sock_server = socket(AF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR)

    {

        cout << "创建套接字失败!错误代码:" << WSAGetLastError() << endl;

        WSACleanup();

        return 0;

    }

    //绑定端口和Ip

    sockaddr_in addr;

    addr.sin_family = AF_INET;

    addr.sin_port = htons(PORT);

    inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);//绑定本机的环回地址

    if (SOCKET_ERROR == bind(sock_server, (SOCKADDR*)&addr, sizeof(sockaddr_in)))

    {

        cout << "地址绑定失败!错误代码:" << WSAGetLastError() << endl;

        closesocket(sock_server);

        WSACleanup();

        return 0;

    }

    //将套接字设为监听状态

    listen(sock_server, 0);

    //主线程循环接收客户端的连接

    while (1)

    {

        sockaddr_in addrClient;

        int len = sizeof(sockaddr_in);

        //接收成功返回与client通讯的socket

        SOCKET con = accept(sock_server, (SOCKADDR*)&addrClient, &len);

        if (con != INVALID_SOCKET)

        {

             //创建线程 并且传入与client通讯的套接字

             HANDLE hThread = CreateThread(NULL, 0, ThreadFun, (LPVOID)con, 0, NULL);

             CloseHandle(hThread); //关闭对线程的引用

        }

    }

    closesocket(sock_server);

    WSACleanup();

    return 0;

}

//线程通讯部分

DWORD WINAPI ThreadFun(LPVOID lpThreadParameter)

{

    //与客户端通讯 先发送再接收数据

    SOCKET sock = (SOCKET)lpThreadParameter;

    cout << "成功和" << sock << "建立连接!" << endl;

    while (1)

    {

        char msgbuffer[1000];//字符缓冲区

        printf("服务器向%d发送信息:\n", sock);

        cin.getline(msgbuffer, sizeof(msgbuffer));

        int size = send(sock, msgbuffer, sizeof(msgbuffer), 0);//给客户端发送一段信息

        if (strcmp(msgbuffer, "end\0") == 0)

        {

             cout << "关闭和" << sock << "的连接!" << endl;

             return 0;

        }

        if (size == SOCKET_ERROR || size == 0)

        {

             cout << "发送信息失败!错误代码:" << WSAGetLastError() << endl;

             return 0;

        }

        else cout << "信息发送成功!" << endl;

        //接收客户端数据

        msgbuffer[999] = { 0 };

        int ret = recv(sock, msgbuffer, sizeof(msgbuffer), 0);

        if (ret == SOCKET_ERROR || ret == 0)

        {

             cout << sock << "断开了连接!" << endl;

            break;

        }

        else cout << sock << " 发来的信息: " << msgbuffer << endl;

    }

    return 0;

}

客户端代码:

#include <winsock2.h>

#include <WS2tcpip.h>

#include <iostream>

using  namespace std;

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

#define PORT 65432

int  main()

{

    //初始化winsock2.DLL

    WSADATA wsaData;

    WORD wVersionRequested = MAKEWORD(2, 2);

    if (WSAStartup(wVersionRequested, &wsaData) != 0)

    {

        cout << "加载winsock.dll失败!" << endl;

        return 0;

    }

    //创建套接字

    SOCKET  sock_client;

    if ((sock_client = socket(AF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR)

    {

        cout << "创建套接字失败!错误代码:" << WSAGetLastError() << endl;

        WSACleanup();

        return 0;

    }

    //连接服务器

    sockaddr_in   addr;

    addr.sin_family = AF_INET;

    addr.sin_port = htons(PORT);

    inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);//绑定本机的环回地址

    int len = sizeof(sockaddr_in);

    if (connect(sock_client, (SOCKADDR*)&addr, len) == SOCKET_ERROR) {

        cout << "连接失败!错误代码:" << WSAGetLastError() << endl;

        return 0;

    }

    //实现交互部分,客户端先接收后发送数据

    while (1)

    {

        //接收服务端的消息

        char msgbuffer[1000] = { 0 };

        int size = recv(sock_client, msgbuffer, sizeof(msgbuffer), 0);

        if (strcmp(msgbuffer, "end\0") == 0)

        {

             cout << "服务器端已经关闭连接!" << endl;

             break;

        }

        if (size < 0)

        {

             cout << "接收信息失败!错误代码:" << WSAGetLastError() << endl;

             break;

        }

        else if (size == 0)

        {

             cout << "对方已经关闭连接" << endl;

             break;

        }

        else cout << "服务器发来消息:" << msgbuffer << endl;

        //从键盘输入一行文字发送给服务器

        msgbuffer[999] = 0;

        cout << "给服务器发送信息:" << endl;

        cin.getline(msgbuffer, sizeof(msgbuffer));

        if (strcmp(msgbuffer, "end\0") == 0)

        {

             cout << "关闭连接!" << endl;

             break;

        }

        int ret = send(sock_client, msgbuffer, sizeof(msgbuffer), 0);

        if (ret == SOCKET_ERROR || ret == 0)

        {

             cout << "发送信息失败!错误代码:" << WSAGetLastError() << endl;

             break;

        }

        else cout << "信息发送成功!" << endl;

    }

    closesocket(sock_client);

    WSACleanup();

    return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值