流式套接字并发服务器【基于流式套接字的网络程序设计】

目录

流式套接字并发服务器

主线程:
创建套接字并将其绑定到服务器所使用的熟知地址上。 重复调用accept接收客户端的请求,并且创建子线程处理响应。

子线程:
在线程创建时接收连接请求; 用该连接与客户端进行交互:接收请求并发回应答; 关闭连接并退出。子线程在处理完来自一个客户端的所有请求后退出

代码实现

#include <winsock2.h>
#include <windows.h>
#define NETWORK1_2_1_A_COMM_H
#define NETWORK1_2_1_A_COMM_H
#include <stdio.h>
#include <stdlib.h>

#include <inaddr.h>
#include <time.h>
#include <string.h>

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

#define MAXLINE 4096     // 接收缓冲区长度
#define LISTENQ 1024     // 监听队列长度
#define SEVER_PORT 13131 // 端口

//初始化动态连接库 
int startUp()
{
    WORD w_version = MAKEWORD(2, 2);
    WSADATA wsa_data;
    int res = WSAStartup(w_version, &wsa_data);
    if (res != 0)
    {
    	printf("WSAStartup Error:%d\n",WSAGetLastError());
        return -1;
    }
    if (LOBYTE(wsa_data.wVersion) != 2 || HIBYTE(wsa_data.wVersion) != 2)
    {
    	printf("版本号错误:%d\n",WSAGetLastError()); 
        WSACleanup();
        return -1;
    }

    return 0; //WSAStartup()成功
}
/*释放动态连接库*/
int cleanUp()
{
    int res = WSACleanup();
    if (res == SOCKET_ERROR)
    {
    	printf("WSACleanup error:%d\n",WSAGetLastError());
        return -1;
    }
    return 0;
}
/*断开连接并释放资源*/
int closeConn(SOCKET sock_conn)
{
    int res = closesocket(sock_conn); //关闭连接
    if (res == SOCKET_ERROR)
    {
    	printf("close socket error:%d",WSAGetLastError());
        return -1;
    }
    res = cleanUp();
    return res;
}
/*Server Init*/
SOCKET tcpServerInit(u_short port)
{
    int res = -1;

    // 设置地址
    sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    server_addr.sin_port = htons(port);

    //创建流式套接字
    SOCKET sock_listen = socket(AF_INET, SOCK_STREAM, 0);
    if (sock_listen == INVALID_SOCKET)
    {
    	printf("Sock error:%d",WSAGetLastError());
        WSACleanup();
        return -1;
    }

    //绑定服务器地址
    res = bind(sock_listen, (struct sockaddr *)&server_addr, sizeof(server_addr));
    if (res == SOCKET_ERROR)
    {
    	printf("bind error:%d\n",WSAGetLastError());
        closeConn(sock_listen);
        return -1;
    }

    //设置服务器为监听状态 最长长度LISTENQ
    res = listen(sock_listen, LISTENQ);
    if (res == SOCKET_ERROR)
    {
    	printf("listen error:%d\n",WSAGetLastError());
        closeConn(sock_listen);
        return -1;
    }

    return sock_listen;
}


/*线程函数*/
void *asyncTcpEchoServer(LPVOID pParam)
{
    int sock_res;
    char recv_data[MAXLINE];

    // 将输入参数转换成连接套接字
    SOCKET sock_conn = *((SOCKET *)pParam);
    do
    {
        memset(recv_data, 0, MAXLINE);

        // 接收数据
        sock_res = recv(sock_conn, recv_data, MAXLINE, 0);
        if (sock_res > 0)
        {
			printf("从客户端接收到的数据:%s\n",recv_data);
  
            // 回射接收的数据
            sock_res = send(sock_conn, recv_data, sock_res, 0);
            if (sock_res == SOCKET_ERROR)
            {
				printf("send error:%s\n",WSAGetLastError());
                sock_res = -1;
            }
            else
            {
				printf("发送的数据为:%s\n",recv_data);
            }
        }
        else
        {
            if (sock_res == 0)
            {
				puts("客户端关闭");
            }
            else
            {
				printf("recv error :%d\n",WSAGetLastError());
                sock_res = -1;
            }
            break;
        }
    } while (sock_res > 0);
    if (sock_res == -1)
    {
		puts("连接失败");
    }
    return NULL;
}

int main(int argc, char *argv[])
{
    int res = -1;
    SOCKET sock_conn;
    SOCKET sock_listen;
    //pthread_t pThread;
	HANDLE hThread;
    char buff[MAXLINE]; //缓冲区

    // 启动
    res = startUp();
    if (res == -1) return -1;

    //监听
    sock_listen = tcpServerInit(SEVER_PORT);
    if (sock_listen == -1) return -1;
	puts("Server  StartUp seccess!");

    while (true)
    {
        //接受客户端连接请求,返回连接套接字sock_conn
        sock_conn = accept(sock_listen, NULL, NULL);

        if (sock_conn != INVALID_SOCKET)
        {
            puts("连接成功");
            // 创建线程
			hThread=CreateThread(NULL,0,asyncTcpEchoServer,&sock_conn,0,NULL);
            //pthread_create(&pThread, nullptr, asyncTcpEchoServer, &sock_conn);
        }
        else
        {
            printf("accept error:%d\n",WSAGetLastError());
            closeConn(sock_listen);
            return -1;
        }
    }
    CloseHandle(hThread);
	Sleep(100);
    // 关闭连接
    closeConn(sock_listen);
    return 0;
}

运行结果

流式套接字并发服务器【基于流式套接字的网络程序设计】

上一篇:linux查看端口号使用情况


下一篇:nginx基本配置与使用--Ubuntu系统