Socket (Client & Server)

来源:互联网 发布:淘宝运营岗位职责 编辑:程序博客网 时间:2024/05/21 22:31

流式套接字实现简单的客户端&服务端通信过程

一 实验内容

1 熟悉流式套接字socket函数的使用方法,包括建立连接、数据发送/接收和关闭连接等;
2 客户端可向服务端发送任意字符串,服务端在接收到该字 符串后,回送给客户端;(此过程可循环)
3 服务端在接收到新连接后,能够打印出客户端的ip和端口;(如何获取连接套接字上的地址信息,请自行查阅资料)
4 服务端采用多线程模式,能够同时接收多个客户端的连接请求,为每个客户端连接开启一个线程;(多线程编程自行查阅资料)

二 实验要求

要求:提交源码(源码编写要规范)、可执行程序、实验报告(要有程序运行截图)。

三 实验过程分析

1.Server

(1)函数

  1. 创建套接字──socket()

  2. 指定本地地址──bind()

  3. 监听信息──listen()

  4. 等待接受信息──accpet()

  5. 数据传送与接收──sendto()与recvfrom()

1.socket:实则为一个句柄SOCKET PASCAL FAR socket(int af, int type, int protocol);  2.bind:bind(    _In_ SOCKET s,    _In_reads_bytes_(namelen) const struct sockaddr FAR * name,//结构体    _In_ int namelen    );    //调用bind()函数之后,为socket()函数创建的套接字关联一个相应地址,发送到这个地址3.listen://监听消息是否到来listen(    _In_ SOCKET s,    _In_ int backlog //消息队列长度    );4.accept:返回值为一个套接字accept(    _In_ SOCKET s,    _Out_writes_bytes_opt_(*addrlen) struct sockaddr FAR * addr,    _Inout_opt_ int FAR * addrlen    );5.sendto/recvfrom:send(    _In_ SOCKET s,//建立过连接的socket    _In_reads_bytes_(len) const char FAR * buf,    _In_ int len,    _In_ int flags    );

(2)多线程实现

多线程的实现利用函数CreateThread实现

CreateThread(    _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,    _In_ SIZE_T dwStackSize,    _In_ LPTHREAD_START_ROUTINE lpStartAddress,加载函数地址    _In_opt_ __drv_aliasesMem LPVOID lpParameter,加载函数参数    _In_ DWORD dwCreationFlags,    _Out_opt_ LPDWORD lpThreadId    );直接在一个新的线程里执行下面代码DWORD WINAPI ClientThread(LPVOID lpParameter){    SOCKET CientSocket = (SOCKET)lpParameter;    int Ret = 0;    int Ret1 = 0;    char RecvBuffer[MAX_PATH];    char SendBuffer[MAX_PATH];    while ( true )    {        memset(RecvBuffer, 0x00, sizeof(RecvBuffer));        Ret = recv(CientSocket, RecvBuffer, MAX_PATH, 0);//接收消息队列中的内容        if ( Ret == 0 || Ret == SOCKET_ERROR )         {            cout<<"客户端退出!"<<endl;            break;        }        cout<<"接收到客户信息为:"<<RecvBuffer<<endl;        cout<<strlen(RecvBuffer);        Ret = send(CientSocket,RecvBuffer, (int)strlen(RecvBuffer), 0);//将接收到的信息直接通过该socket转发至客户端    }    return 0;}

Client

(1)函数

  1. 创建套接字──socket()

  2. 连接服务端──connect()

  3. 数据传送与接收──sendto()与recvfrom()

connect:connect(    _In_ SOCKET s,    _In_reads_bytes_(namelen) const struct sockaddr FAR * name,    _In_ int namelen    );
发送信息的代码:    while ( true )    {        cout<<"send:";        cin>>SendBuffer;        Ret = send(ClientSocket, SendBuffer, (int)strlen(SendBuffer), 0);        if ( Ret == SOCKET_ERROR )        {            cout<<"Send Info Error::"<<GetLastError()<<endl;            break;        }        Ret1 = recv(ClientSocket , RecvBuffer, MAX_PATH, 0);//接收到服务器的回显        cout<<"get:"<<RecvBuffer<<endl;    }

四 实验代码测试

hThread = CreateThread(NULL, 0, ClientThread, (LPVOID)ClientSocket, 0, NULL);其中第三个参数为回调函数,第四个函数为回调函数的参数

服务器端
这里写图片描述
客户端1
这里写图片描述

将下面代码注释掉,在执行即为单线程不能同时处理多个客户端的请求

//  hThread = CreateThread(NULL, 0, ClientThread, (LPVOID)ClientSocket, 0, NULL);··············    if ( hThread == NULL )        {            cout<<"Create Thread Failed!"<<endl;            break;        }        CloseHandle(hThread);            i++;    }

这里写图片描述
发现最后一个连接的客户端无法实现信息回显,说明在单线程下服务器端无法支持多站点访问。只有在每次与客户端连接成功时,创建新的线程去响应相关操作,才会实现多客户端连接的情况。

0 0
原创粉丝点击