C++的socket编程学习

前言

  不得不承认作为一个前端开发,仍有一个后台开发的梦。从socket通信开始学习,在工作之余补充学习点相关知识,记录下学习的过程。

  PS:有园友可以推荐点相关的书籍吗?

服务端

  服务器代码如下,在设置listen之后,通过accept获取对应的socket连接并创建线程进行通信,通信完成后关闭对应线程。

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

#include "stdafx.h"
#include <stdio.h>
#include <Winsock2.h>
#pragma comment(lib, "ws2_32.lib")

#define LISTEN_MAX_COUNT 5

DWORD WINAPI AnswerThread(LPVOID lparam)
{
    printf("Thread ID:%4d create!\n", GetCurrentThreadId());
    int                 ret;
    char                buf[50] = { 0 };
    char                sendBuf[80] = { 0 };
    SOCKET              clientSocket = (SOCKET)(LPVOID)lparam;
    while (true)
    {
        memset(buf, 0, sizeof(buf));
        ret = recv(clientSocket, buf, sizeof(buf), 0);
        if (ret<=0)
        {
            break;
        }
        printf("revc: %s\n", buf);
        sprintf_s(sendBuf, "Thread ID:%4d revced", GetCurrentThreadId());
        ret = send(clientSocket, sendBuf, strlen(sendBuf) + sizeof(char), 0);
        if (ret <= 0)
        {
            break;
        }
    }
    printf("Thread ID:%4d stop!\n", GetCurrentThreadId());
    closesocket(clientSocket);
    return 1;
}

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

    WORD wVersionRequested;
    WSADATA wsaData;
    wVersionRequested = MAKEWORD(1, 1);
    if (WSAStartup(wVersionRequested, &wsaData) == INVALID_SOCKET)
    {
        return 0;
    }

    if (LOBYTE(wsaData.wVersion) != 1 ||
        HIBYTE(wsaData.wVersion) != 1) {
        WSACleanup();
        return 0;
    }
    SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0);
    int len = sizeof(SOCKADDR);
    SOCKADDR_IN clientAddr;
    SOCKADDR_IN serviceAddr;
    serviceAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    serviceAddr.sin_family = AF_INET;
    serviceAddr.sin_port = htons(27015);

    if (bind(sockSrv, (SOCKADDR*)&serviceAddr, len) == INVALID_SOCKET)
    {
        printf("failed bind!\n");
        closesocket(sockSrv);
        WSACleanup();
        return 0;
    }
    if (listen(sockSrv, LISTEN_MAX_COUNT) == SOCKET_ERROR) {
        printf("Listen failed with error: %ld\n", WSAGetLastError());
        closesocket(sockSrv);
        WSACleanup();
        return 0;
    }

    SOCKET  sockClient;
    HANDLE  hThread = NULL;
    DWORD    dwThreadId;
    while (1)
    {
        sockClient = accept(sockSrv, (SOCKADDR*)&clientAddr, &len);
        Sleep(1000);
        hThread = CreateThread(NULL, NULL, AnswerThread, (LPVOID)sockClient, 0, &dwThreadId);
        if (hThread == NULL)
        {
            printf("CreatThread AnswerThread() failed.\n");
        }
    }

    closesocket(sockSrv);
    WSACleanup();
    return 0;
}

客户端

   客户端代码如下,在连接成功后,循环输入进行通信对话。

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

#include "stdafx.h"
#include <stdio.h>
#include <Winsock2.h>

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

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

    WORD wVersionRequested;
    WSADATA wsaData;
    int err;

    wVersionRequested = MAKEWORD(1, 1);
    if (WSAStartup(wVersionRequested, &wsaData) == INVALID_SOCKET)
    {
        return -1;
    }

    if (LOBYTE(wsaData.wVersion) != 1 ||
        HIBYTE(wsaData.wVersion) != 1) {
        WSACleanup();
        return -1;
    }

    SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);
    int len = sizeof(SOCKADDR);

    SOCKADDR_IN local;
    local.sin_addr.S_un.S_addr = inet_addr("192.168.1.15");
    local.sin_family = AF_INET;
    local.sin_port = htons(27015);

    if (connect(sockClient, (SOCKADDR*)&local, len) == INVALID_SOCKET)
    {
        printf("connect error/n");
        return 0;
    }

    char inputBuf[30];
    char recvBuf[50];
    int ret;
//    while (scanf_s("%s", inputBuf, sizeof(inputBuf)) != EOF)
    while (gets_s(inputBuf))
    {
        if (strcmp(inputBuf, "stop") ==0)
        {
            break;
        }
        ret = send(sockClient, inputBuf, strlen(inputBuf) + sizeof(char), 0);
        if (ret<=0)
        {
            printf("send failed!\n");
            break;
        }
        ret = recv(sockClient, recvBuf, sizeof(recvBuf), 0);
        if (ret <= 0)
        {
            printf("recv failed!\n");
            break;
        }
        printf("my reply is : %s\n", recvBuf);
        //printf("%s\n", inet_ntoa(local.sin_addr));
    }

    closesocket(sockClient);
    WSACleanup();
    return 0;
}

测试

  Hello World!!

1、开启多个客户端,可以看到服务器如下输出多个线程的创建。

  

2、客户端输入hello world!,可以得到服务器回复,并告知哪个服务器线程接收了消息。

  

3、关闭其中一个客户端,可以看到对应线程也关闭了。

4、关闭服务端后,可以端输入任意内容,可以看到客户端也收到提示发送失败并关闭。

时间: 2024-08-06 09:30:51

C++的socket编程学习的相关文章

Android Socket编程学习笔记

通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄.在Internet上的主机一般运行了多个服务软件,同时提供几种服务.每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务. 网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向链路的一端称为一个Socket.Socket通常用来实现客户方和服务方的连接.Socket是TCP/IP协议的一个十分流行的编程界面,一个Socket由一个IP地址和一个端口号唯一确定. 在java中,Socke

Socket编程学习之道:揭开Socket编程的面纱

对TCP/IP.UDP.Socket编程这些词你不会很陌生吧?随着网络技术的发展,这些词充斥着我们的耳朵.那么我想问: 1.         什么是TCP/IP.UDP? 2.         Socket在哪里呢? 3.         Socket是什么呢? 4.         你会使用它们吗? 什么是TCP/IP.UDP? TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,是一个工业标准的协议集,它是为

JAVA Socket 编程学习笔记(二)

在上一篇中,使用了 java Socket+Tcp/IP  协议来实现应用程序或客户端--服务器间的实时双向通信,本篇中,将使用 UDP 协议来实现 Socket 的通信. 1. 关于UDP UDP协议(用户数据报协议)是无连接的.不可靠的.无序的,速度快,进行数据传输时,首先将要传输的数据定义成数据报(Datagram),大小限制在64k,在数据报中指明数据索要达到的Socket(主机地址和端口号),然后再将数据报发送出去,Java 对UDP 协议通信提供了两个主要的类,DatagramPac

JAVA Socket 编程学习笔记(一)

1. Socket 通信简介及模型 Java Socket 可实现客户端--服务器间的双向实时通信.java.net包中定义的两个类socket和ServerSocket,分别用来实现双向连接的client和server端. 2. Socket 通信实现方法 2.1  服务器端(非多线程)  用指定的端口实例化一个SeverSocket对象.服务器就可以用这个端口监听从客户端发来的连接请求. 调用ServerSocket的accept()方法,以在等待连接期间造成阻塞,监听连接从端口上发来的连接

IOS的socket编程学习笔记

苹果的Socket编程,常用的是CFNetwork库编程,Socket编程是一个异步的过程,socket的联接方法,不是会等到连接完成后再执行下一行代码,如果你想在一个连接完全执行完之前与一个Socket完全绑定,那么就会容易得到一个意想不到的结果.     连接一台Socket服务器你需要确定两个信息,一个是Socket服务器的域名或者IP地址,另一个是服务器监听的端口号.在尝试一个新的Socket连接的时候我们最好先添加一个连接事件监听器.     CFNetwork库编程,其封装好的开源库

Java Tcp协议socket编程学习

以下是一对一的通信编程实现,后续会继续学习一个服务器监听多个客户端的实现. 我学习到的主要步骤 第一步:以特定端口(如4800)新建socket对象第二步:以系统输入设备构造BufferedReader对象,该对象用于接收系统键盘输入的字符第三步:以socket对象 得到输出流来构造PrintWriter第四步:以socket对象得到输入流来构造相应的BufferedReader对象,该对象用于接收server端发送过来的信息 我理解到的关闭socket:先开的后关闭,socket最后关闭. 以

python socket编程学习笔记2

 server.py: [服务端步骤]: 1.创建socket对象 2.将socket绑定到指定地址(bind) 3.监听连接请求(listen) 4.等待客户请求(accept) 5.处理请求(服务器和客户端通过send和recv方法通信(传输 数据). 6.传输结束后关闭连接(close) client.py: [客户端步骤]: 1.创建socket对象 2.创建连接(connect) 3.处理阶段(send方法和recv方法通信) 4.关闭连接 (close)

socket编程学习step2

引言:主机之间如何相互交互呢?网络层的“ip地址”可以唯一标识网络中的主机,而传输层的“协议+端口“可以唯一标识主机中的应用进程.这样利用三元组(ip地址,协议,端口)就可以标识网络的进程了,网络中的进程就可以利用这个标志与其他主机进行交互了. 什么是TCP/IP.UDP? 1.TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,面向连接.保证高可靠性的传输层协议. 1)TCP/IP协议存在于OS中,网络服务通过

socket编程学习

基于udp的socket udp是无连接的,那边先启动不会报错 udp的小例子: 1 from socket import * 2 ip_port=('127.0.0.1',8888) 3 buffer_size=1024 4 myudp_server=socket(AF_INET,SOCK_DGRAM) 5 myudp_server.bind(ip_port) 6 while True: 7 message,addr=myudp_server.recvfrom(buffer_size) 8 p