欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

面向连接的套接字编程

最编程 2024-07-09 13:49:32
...

一、 实验目的

1.了解Socket的工作原理、服务方式和类型。

2.了解Socket应用程序的框架结构及相关数据结构。

3.理解面向连接的Socket通信流程。

4.掌握使用WinSock函数编写面向连接的网络应用程序的方法。

二、实验内容和要求

1.编写Windows平台上的基于TCP套接字的服务器应用程序TcpServer。服务器端接收客户端发送的消息,显示收到消息的来源、时间和消息内容,并向客户端回送信息进行接收确认。

2.编写Windows平台上的基于TCP套接字的客户端应用程序TcpClient。客户端程序主动发起与服务器程序的连接,读取用户输入的信息并向服务器发送,并接收服务器端的回送信息。

3.在同一台或不同计算机上分别运行TcpServer和TcpClient进行消息的发送和接收测试。要求建立连接后客户端可连续多次向服务器端发送消息。

4.使用Windows命令分别查看TcpServer和TcpClient的TCP连接信息和进程信息。

三、实验原理

1.在server端,server首先启动,调用socket()创建套接字;然后调用bind()绑定server的地址(IP+port);再调用listen()让server做好侦听准备,并规定好请求队列长度,然后server进入阻塞状态,等待client的连接请求;最后通过accept()来接收连接请求,并获得client的地址。当accpet接收到一个client发来的connet请求时,将生成一个新的socket,用于传输数据。

2.在client端,client在创建套接字并指定client的socket地址,然后就调用connect()和server建立连接。一旦连接建立成功,client和server之间就可以通过调用recv和send来接收和发送数据。一旦数据传输结束,server和client通过调用close()来关闭套接字。

3.流程图:

主要函数说明:

1.Socket():用于创建与指定的服务提供绑定套接字。

2.Bind():将本地地址与socket绑定在一起。

3.Listen():将套接字设置为监听接入连接的状态。

4.accept():服务器端调用listen()函数监听接入连接后,可以调用accept()函数来等待接受连接请求。

5.recv():从已连接的socket中接收数据。

6.send():在已建立连接的socket上发送数据。

7.closesocket():关闭一个socket,释放所占有的资源。

8.connect():用于建立到socket的连接,该socket必须处于监听状态。

四、运行结果:

1.成功建立连接

2.在客户端上输入信息后,服务端可以接收发来的信息

3.Quit 退出

4. 0.0.0.0:9990端口上有一个TCP处于LINSTENING状态

5.本地IP端口9990上有一个TCP连接处于ESTANLISHED状态。

五、实验小结

1.分别建立两个方案,来运行服务端和客服端。用C++来实现本程序。

2.运行服务器程序后,可以在cmd查看服务器程序是否处于监听状态。

3.再此基础上运行客服端程序,执行 netstat –nao 可以看到本机IP的9990端口上,有一个TCP连接处于建立连接状态。

附:「Visual Studio 2012.exe」https://www.aliyundrive.com/s/kJnjpnmF1Nn 提取码: f1h1 。

附:程序源代码

TcpServer服务器端应用程序源代码:

#include "stdafx.h"

#include <WINSOCK2.H>

#include <iostream>

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

#define BUF_SIZE 64            

 

int _tmain(int argc, _TCHAR* argv[])

{

    WSADATA wsd;

    SOCKET sServer;

    SOCKET sClient;

    int retVal;

    char buf[BUF_SIZE];

 

    //初始化Socket

    if(WSAStartup(MAKEWORD(2,2),&wsd) != 0)

    {

        printf("WSAStartup failed !\n");

        return 1;

    }

    printf("服务器初始化成功!\n");

 

    //创建用于监听的socket

    sServer = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

    if(INVALID_SOCKET == sServer)

    {

        printf("socket failed !\n");

        WSACleanup();

        return -1;

    }

    printf("服务器创建用于监听套接字成功!\n");

 

    //设置服务器socket地址

    SOCKADDR_IN addrServ;

    addrServ.sin_family =AF_INET;

    addrServ.sin_port = htons(9990);

    addrServ.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

    printf("设置服务器socket地址成功!\n");

 

    //绑定socket server到本地地址

    retVal = bind(sServer,(const struct sockaddr*)&addrServ,sizeof(SOCKADDR_IN));

    if(SOCKET_ERROR == retVal)

    {

        printf("bond failed !\n");

        closesocket(sServer);

        WSACleanup();

        return -1;

    }

    printf("服务器绑定socket server到本地地址成功!\n");

 

    //在sockets server上进行监听

    retVal = listen(sServer,1);

    if(SOCKET_ERROR == retVal)

    {

        printf("listen failed !\n");

        closesocket(sServer);

        WSACleanup();

        return -1;

    }printf("服务器以处于监听状态!\n");

   

    //接受来之客户端的请求

    printf("TCP Server start...\n");

    sockaddr_in addrClient;   //客户端地址

    int addrClientlen = sizeof(addrClient);

    sClient = accept(sServer,(sockaddr FAR*)&addrClient,&addrClientlen);

    if(INVALID_SOCKET == sClient)

    {

        printf("accept failed !\n");

        closesocket(sServer);

        WSACleanup();

        return -1;

    }printf("服务器以与一个客户端建立连接...\n");

   

    //循环接受客户端的数据,直接客户端发送quit命令后退出

    while(true)

    {

        printf("服务器开始接收客户端数据...\n");

        ZeroMemory(buf,BUF_SIZE);

        retVal = recv(sClient,buf,BUF_SIZE,0);

        printf("接收客户端的数据: %s\n",buf);

        if(SOCKET_ERROR == retVal)

        {

             printf("recv failed !\n");

             closesocket(sServer);

             closesocket(sClient);

             WSACleanup();

             return -1;

        }

        //获取当前系统时间

        SYSTEMTIME st;

        GetLocalTime(&st);

        char sDateTime[30];

        sprintf(sDateTime,"%4d-%2d-%2d %2d:%2d:%2d",st.wYear,st.wMonth,st.wDay,st.wHour,st.wMinute,st.wSecond);

        //打印输出的信息

        printf("%s,Recv From Client [%S:%d] :%s\n",sDateTime,inet_ntoa(addrClient.sin_addr),addrClient.sin_port,buf);

        //如果客户端发送“quit”字符串,则服务器退出

        if(strcmp(buf,"quit")==0)

        {

             retVal = send(sClient,"quit",strlen("quit"),0);

             break;

        }

        //否则向客户端发送回显字符串

        else

        {

             char msg[BUF_SIZE];

             sprintf(msg,"Message received - %s",buf);

             retVal = send(sClient,msg,strlen(msg),0);

             if (SOCKET_ERROR == retVal)

             {

                 printf("send failed !\n");

                 closesocket(sServer);

                 closesocket(sClient);

                 WSACleanup();

                 return -1;

             }

        }

    }

 

    //释放socket

    closesocket(sServer);

    closesocket(sClient);   

    WSACleanup();

 

    //暂停,按任意键退出

    system("pause");

    return 0;

}

 

TcpClient客户端应用程序源代码:

// TcpClient.cpp : 定义控制台应用程序的入口点。

//

 

#include "stdafx.h"

#include <WINSOCK2.H>

#include <string>

#include <iostream>

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

#define BUF_SIZE 64

 

 

int _tmain(int argc, _TCHAR* argv[])

{

    WSADATA wsd;

    SOCKET sHost;

    SOCKADDR_IN servAddr;

    char buf[BUF_SIZE];

    int retVal;

 

    //初始化Socket环境

    if(WSAStartup(MAKEWORD(2,2),&wsd)!=0)

    {

      printf("WSAStartup failed !\n");

      return 1;

    }

 

    //创建套接字

    sHost = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

    if(INVALID_SOCKET == sHost)

    {

      printf("socket failed !\n");

      WSACleanup();

      return -1;

    }

 

    //设置服务器Socket地址

    servAddr.sin_family = AF_INET;

    //用户需要根据实际情况修改

    servAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");

    //在实际应用中,建议将服务器的IP地址和端口号保存在配置文件中

    servAddr.sin_port=htons(9990);

    //计算地址的长度

    int sServerAddlen = sizeof(servAddr);

 

 

    //连接服务器

    printf("TcpClient trying to connect to TcpServer...\n");

    retVal = connect(sHost,(LPSOCKADDR)&servAddr,sizeof(servAddr));

    if(SOCKET_ERROR == retVal)

    {

      printf("Connet to TcpServer failed !\n");

      closesocket(sHost);

      WSACleanup();

      return -1;

    }

 

    while(true)

    {

      printf("Please input a string to send:");

      std::string str;

      //接收输入的数据

      std::getline(std::cin,str);

      //将用户输入的数据复制到buf中

      ZeroMemory(buf,BUF_SIZE);

      strcpy(buf,str.c_str());

      //向服务器发送数据

      retVal = send(sHost,buf,strlen(buf),0);

      if(SOCKET_ERROR==retVal)

      {

       printf("send failed ! \n");

       closesocket(sHost);

       WSACleanup();

         return -1;

      }

      //接收服务器回传的数据

      retVal = recv(sHost,buf,sizeof(buf)+1,0);

      printf("Recv From Server: %s\n",buf);

      //如果收到“quit”,则退出

      if(strcmp(buf,"quit")==0)

      {

        printf("quit!\n");

        break;

      }

 

    }

    printf("客户端数据发送完成!\n");

 

    //释放资源

    closesocket(sHost);

    WSACleanup();

    //暂停,按任意键继续

    system("pause");

    return 0;

}

原文地址:https://www.cnblogs.com/mymck/p/16081009.html