【Socket编程】使用C++实现Server端和Client端

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zgljl2012/article/details/44840763

我是在Visual Stdio 2013上建立了两个工程,分别编译运行下面的两个main文件,然后进行测试的

服务端:Server.cpp

#include <WINSOCK2.H>

#include <iostream>
using std::cout;
using std::cin;
using std::endl;

#include <string>
using std::string;

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

void main()
{
    //创建套接字
    WORD myVersionRequest;
    WSADATA wsaData;                    //包含系统所支持的WinStock版本信息
    myVersionRequest = MAKEWORD(1, 1);  //初始化版本1.1
    int err;
    err = WSAStartup(myVersionRequest, &wsaData);
    if (!err){
        printf("已打开套接字\n");
    }
    else{
        //进一步绑定套接字
        printf("套接字未打开!");
        return;
    }
    SOCKET serSocket = socket(AF_INET, SOCK_STREAM, 0);//创建了可识别套接字
    //需要绑定的参数
    SOCKADDR_IN addr;
    addr.sin_family = AF_INET;
    addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//ip地址
    addr.sin_port = htons(3000);//绑定端口
    //将套接字绑定到指定的网络地址
    bind(serSocket, (SOCKADDR*)&addr, sizeof(SOCKADDR));//绑定完成
    listen(serSocket, 10);                              //第二个参数代表能够接收的最多的连接数
    SOCKADDR_IN clientsocket;
    int len = sizeof(SOCKADDR);
    SOCKET serConn;
    //等待客户端的连接
    serConn = accept(serSocket, (SOCKADDR*)&clientsocket, &len);
    cout << "客户端" << inet_ntoa(clientsocket.sin_addr) << "已连接" << endl;             //客户端已连接
    while (1) {
        char sendBuf[100];
        sprintf(sendBuf, "server : welcome %s to server.", inet_ntoa(clientsocket.sin_addr));
        //在对应的IP处并且将这行字打印到那里
        send(serConn, sendBuf, strlen(sendBuf) + 1, 0);
        char receiveBuf[100];
        //接收客户端传来的信息
        recv(serConn, receiveBuf, strlen(receiveBuf) + 1, 0);
        char* quit = "quit";
        //如果客户端传来了quit信号,则服务端关闭,客户端也关闭
        if (!strcmp(receiveBuf, quit)) {
            break;
        }
        printf("%s\n", receiveBuf);
    }
    closesocket(serConn);   //关闭
    WSACleanup();           //释放资源的操作
}

客户端:Client.cpp

#include <WINSOCK2.H>

#include <iostream>
using std::cout;
using std::cin;
using std::endl;
#include <string>
using std::string;
#include <conio.h>

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

void main()
{
    int err;
    WORD versionRequired;
    WSADATA wsaData;                            //包含系统所支持的WinStock版本信息
    versionRequired = MAKEWORD(1, 1);           //初始化版本1.1
    //注册WinStock,返回状态
    err = WSAStartup(versionRequired, &wsaData);//协议库的版本信息
    if (!err)                                   //返回结果为0表示初始化失败
    {
        cout << LPSTR("客户端套接字已经打开!\n");
    }
    else
    {
        //调用WSAGetLastError()查看错误信息
        cout << ("客户端套接字打开失败:") << WSAGetLastError() << endl;
        return;//结束
    }
    /*
    创建套接字:
    流式套接字:   SOCK_STREAM , IPPROTO_TCP
    数据报套接字: SOCK_DGRAM  , IPPROTO_UDP
    */
    SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);    //创建流式套接字
    SOCKADDR_IN clientsock_in;                                          //专门针对Internet 通信域的Winsock地址结构
    clientsock_in.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");        //通过inet_addr结构指定套接字的主机IP地址 
    clientsock_in.sin_family = AF_INET;                                 //指定协议家族:AF_INET
    clientsock_in.sin_port = htons(3000);                               //指定将要分配给套接字的传输层端口号:6000

    int fail = connect(clientSocket, (SOCKADDR*)&clientsock_in, sizeof(SOCKADDR));//开始连接
    if (fail){
        cout << "与服务端连接失败!程序将退出..." << endl;
        _getch();
        return;
    }
    string s;
    while (cin >> s){
        char receiveBuf[100];
        //接收数据
        recv(clientSocket, receiveBuf, 101, 0);
        cout << receiveBuf <<endl;
        //发送数据
        send(clientSocket, s.c_str(), s.length() + 1, 0);
        if (s == "quit"){
            break;
        }
    }
    closesocket(clientSocket);
    //关闭套接字
    if (WSACleanup() == SOCKET_ERROR){
        cout << "套接字关闭失败:" << WSAGetLastError() << endl;
    }
    else{
        cout << "套接字成功关闭." << endl;
    }
    _getch();
    return;
}
//inet_addr结构:
/*
Struct in_addr {
Union{
Struct{ u_char s_b1, s_b2, s_b3, s_b4; } S_un_b;
Struct{ u_short s_w1, s_w2; } S_un_w;
U_long  S_addr;
}
}
*/

测试

这里写图片描述
客户端输入quit后,客户端和服务端则均可正常退出;否则,只关闭客户端,服务端会陷入无限循环输出最后传送的数据(可叉掉)。

备注:

  • 不能支持中文传送数据(会有乱码);
  • 在客户端输入有空格的数据时,会被当成多次输入数据(因为是使用cin读取的数据)

    阅读更多
    换一批

    没有更多推荐了,返回首页