【C++网络编程】Socket基础:网络通讯程序入门级教程

简介: 【C++网络编程】Socket基础:网络通讯程序入门级教程

image.gif

🌞前言

在这篇文章里我们会实现一个小项目:客服端通过socket与服务器建立连接,并且发送消息。项目详情如下:

  • 编程语言:C++
  • 运行环境:Ubuntu
  • 项目技术:socket



🌞一、基本概念

网络通讯是指两台计算机中的程序进行传输消息的过程。

  • 客户端∶指主动发起通讯的程序。
    客户端必须提前知道服务端的IP地址和通讯端口。
  • 服务端∶指被动的等待,然后为向它发起通讯的客户端提供服务。
    服务端不需要知道客户端的IP地址。

🌞二、第一个网络通讯程序

🌼2.1 网络通讯的流程示意图


🌼2.2 程序模块

客户端client.cpp

/*
 * 程序名:client.cpp,此程序用于演示socket的客户端
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
using namespace std;
 
int main(int argc,char *argv[])
{
  if (argc!=3)
  {
    cout << "Using:./client 服务端的IP 服务端的端口\nExample:./client 192.168.101.139 5005\n\n"; 
    return -1;
  }
 
  /* 第1步:创建客户端的socket。  */
  int sockfd = socket(AF_INET,SOCK_STREAM,0);
  if (sockfd==-1)
  {
    perror("socket"); return -1;
  }
 
  /* 第2步:向服务器发起连接请求。*/ 
  struct hostent* h;    // 用于存放服务端IP的结构体。
  if ( (h = gethostbyname(argv[1])) == 0 )  // 把字符串格式的IP转换成结构体。
  { 
    cout << "gethostbyname failed.\n" << endl; close(sockfd); return -1;
  }
  struct sockaddr_in servaddr;              // 用于存放服务端IP和端口的结构体。
  memset(&servaddr,0,sizeof(servaddr));
  servaddr.sin_family = AF_INET;
  memcpy(&servaddr.sin_addr,h->h_addr,h->h_length); // 指定服务端的IP地址。
  servaddr.sin_port = htons(atoi(argv[2]));         // 指定服务端的通信端口。
  
  if (connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr))!=0)  // 向服务端发起连接清求。
  { 
    perror("connect"); close(sockfd); return -1; 
  }
  
  /* 第3步:与服务端通讯,客户发送一个请求报文后等待服务端的回复,收到回复后,再发下一个请求报文。*/
  char buffer[1024];
  for (int ii=0;ii<3;ii++)  // 循环3次,将与服务端进行三次通讯。
  {
    int iret;
    memset(buffer,0,sizeof(buffer));
    sprintf(buffer,"这是第%d个超级女生,编号%03d。",ii+1,ii+1);  // 生成请求报文内容。
    // 向服务端发送请求报文。
    if ( (iret=send(sockfd,buffer,strlen(buffer),0))<=0)
    { 
      perror("send"); break; 
    }
    cout << "发送:" << buffer << endl;
 
    memset(buffer,0,sizeof(buffer));
    /* 接收服务端的回应报文,如果服务端没有发送回应报文,recv()函数将阻塞等待。*/
    if ( (iret=recv(sockfd,buffer,sizeof(buffer),0))<=0)
    {
       cout << "iret=" << iret << endl; break;
    }
    cout << "接收:" << buffer << endl;
 
    sleep(1);
  }
 
  /* 第4步:关闭socket,释放资源。*/
  close(sockfd);
}

服务端server.cpp

/*
 * 程序名:server.cpp,此程序用于演示socket通信的服务端
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
using namespace std;
 
int main(int argc,char *argv[])
{
  if (argc!=2)
  {
    cout << "Using:./server 通讯端口\nExample:./server 5005\n\n";   // 端口大于1024,不与其它的重复。
    cout << "注意:运行服务端程序的Linux系统的防火墙必须要开通5005端口。\n";
    cout << "      如果是云服务器,还要开通云平台的访问策略。\n\n";
    return -1;
  }
 
  // 第1步:创建服务端的socket。 
  int listenfd = socket(AF_INET,SOCK_STREAM,0);
  if (listenfd==-1) 
  { 
    perror("socket"); return -1; 
  }
  
  // 第2步:把服务端用于通信的IP和端口绑定到socket上。 
  struct sockaddr_in servaddr;          // 用于存放服务端IP和端口的数据结构。
  memset(&servaddr,0,sizeof(servaddr));
  servaddr.sin_family = AF_INET;        // 指定协议。
  servaddr.sin_addr.s_addr = htonl(INADDR_ANY); // 服务端任意网卡的IP都可以用于通讯。
  servaddr.sin_port = htons(atoi(argv[1]));     // 指定通信端口,普通用户只能用1024以上的端口。
  // 绑定服务端的IP和端口。
  if (bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr)) != 0 )
  { 
    perror("bind"); close(listenfd); return -1; 
  }
 
  // 第3步:把socket设置为可连接(监听)的状态。
  if (listen(listenfd,5) != 0 ) 
  { 
    perror("listen"); close(listenfd); return -1; 
  }
 
  // 第4步:受理客户端的连接请求,如果没有客户端连上来,accept()函数将阻塞等待。
  int clientfd=accept(listenfd,0,0);
  if (clientfd==-1)
  {
    perror("accept"); close(listenfd); return -1; 
  }
 
  cout << "客户端已连接。\n";
 
  // 第5步:与客户端通信,接收客户端发过来的报文后,回复ok。
  char buffer[1024];
  while (true)
  {
    int iret;
    memset(buffer,0,sizeof(buffer));
    // 接收客户端的请求报文,如果客户端没有发送请求报文,recv()函数将阻塞等待。
    // 如果客户端已断开连接,recv()函数将返回0。
    if ( (iret=recv(clientfd,buffer,sizeof(buffer),0))<=0) 
    {
       cout << "iret=" << iret << endl;  break;   
    }
    cout << "接收:" << buffer << endl;
 
    strcpy(buffer,"ok");  // 生成回应报文内容。
    // 向客户端发送回应报文。
    if ( (iret=send(clientfd,buffer,strlen(buffer),0))<=0) 
    { 
      perror("send"); break; 
    }
    cout << "发送:" << buffer << endl;
  }
 
  // 第6步:关闭socket,释放资源。
  close(listenfd);   // 关闭服务端用于监听的socket。
  close(clientfd);   // 关闭客户端连上来的socket。
}

🌞三、运行测试

小伙伴可以在虚拟机或者购买服务器上运行喔,要求ubuntu环境。可以连接到同一个服务器,也可以连接到多个不同的服务器,这里我们指定一个为客户端client,一个为服务端server。


🌻3.1 准备工作

将上面两个cpp文件创建完成,显示如下:

使用xshell两次连接到同一个服务器【有多个服务器也可以让xshell连接到不同的服务器】,这里我们指定一个为客户端client,一个为服务端server。


🌻3.2 编译

客户端:

//编译client.cpp命令
g++ -g -o client client.cpp

服务端:

//编译server.cpp命令
g++ -g -o server server.cpp


🌻3.3 运行

查看服务器的IP地址

ip addr show

IP地址显示是172.23.23.16

服务端

打开服务端的连接,让服务器处于监听状态(ctrl+c可以退出):

//2003是端口号
./server 2003

客户端

再打开客户端的连接,让其访问服务端+建立连接:

//172.23.23.16是IP地址,2003是端口号
./client 172.23.23.16 2003

查看服务端内容:


🌞四、程序分析

🌷4.1 客户端程序

client.cpp是一个简单的客户端程序,用于与服务器进行通讯。让我们分步来看:

命令行参数检查

  if (argc!=3)
  {
    cout << "Using:./client 服务端的IP 服务端的端口\nExample:./client 192.168.101.139 5005\n\n"; 
    return -1;
  }

这段代码是在程序开始时对命令行参数进行检查。程序预期接收两个参数:服务端的IP地址和端口号。argc表示命令行参数的数量,argv是一个指向参数数组的指针。

argc != 3:检查参数数量是否等于3,如果不等于3,说明用户没有提供正确的参数数量。

这里执行客户端命令用的是./client 172.23.23.16 2003参数分别是:

  • ./client:表示程序名称。
  • 172.23.23.16:表示服务端的IP地址。
  • 2003:表示服务端的通讯端口。

1.创建客户端socket

  /* 第1步:创建客户端的socket。  */
  int sockfd = socket(AF_INET,SOCK_STREAM,0);
  if (sockfd==-1)
  {
    perror("socket"); return -1;
  }

这段程序的作用是创建客户端的套接字(socket),并进行创建的错误检查。程序分析:

  • int sockfd = socket(AF_INET, SOCK_STREAM, 0);这行代码创建了一个套接字,其中:
  • AF_INET 指定了套接字的地址族为IPv4。
  • SOCK_STREAM 指定了套接字的类型为流式套接字,即TCP套接字。
  • 0 表示使用默认的协议。
  • if (sockfd == -1)
    这个条件判断检查套接字是否创建成功。如果套接字创建失败,socket() 函数返回 -1,程序通过 perror("socket") 输出相关错误信息,然后返回 -1 表示程序执行失败。

2.将服务端发送连接请求

  /* 第2步:向服务器发起连接请求。*/ 
  struct hostent* h;    // 用于存放服务端IP的结构体。
  if ( (h = gethostbyname(argv[1])) == 0 )  // 把字符串格式的IP转换成结构体。
  { 
    cout << "gethostbyname failed.\n" << endl; close(sockfd); return -1;
  }
  struct sockaddr_in servaddr;              // 用于存放服务端IP和端口的结构体。
  memset(&servaddr,0,sizeof(servaddr));
  servaddr.sin_family = AF_INET;
  memcpy(&servaddr.sin_addr,h->h_addr,h->h_length); // 指定服务端的IP地址。
  servaddr.sin_port = htons(atoi(argv[2]));         // 指定服务端的通信端口。
  
  if (connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr))!=0)  // 向服务端发起连接清求。
  { 
    perror("connect"); close(sockfd); return -1; 
  }

这段程序的作用是向服务器发起连接请求。程序分析:

  • struct hostent* h;
    声明了一个指向 hostent 结构体的指针,用于存放服务端的IP地址信息。
  • if ((h = gethostbyname(argv[1])) == 0)
    调用 gethostbyname() 函数,把服务端IP地址从字符串类型转换成 hostent 结构体。如果转换失败(返回值为0),则输出错误信息并关闭套接字 sockfd,然后返回 -1。
  • struct sockaddr_in servaddr;
    声明 sockaddr_in 结构体变量 servaddr,用于存放服务端的IP地址和端口号信息。
  • memset(&servaddr, 0, sizeof(servaddr));
    使用 memset() 函数将 servaddr 结构体清零,以便后续使用。
  • servaddr.sin_family = AF_INET;
    设置 servaddr 结构体中的地址族为 IPv4。
  • memcpy(&servaddr.sin_addr, h->h_addr, h->h_length);
    将通过 gethostbyname() 函数获取的服务端IP地址复制到 servaddr 结构体中的 sin_addr 字段。
  • servaddr.sin_port = htons(atoi(argv[2]));
    将命令行参数中的服务端通信端口号转换成整数并转换成网络字节序(大端序),然后存放在 servaddr 结构体中的 sin_port 字段。
  • if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0)
    使用 connect() 函数向服务端发起连接请求。如果连接失败,则输出错误信息,关闭套接字 sockfd,然后返回 -1。

3.与服务端通讯

  /* 第3步:与服务端通讯,客户发送一个请求报文后等待服务端的回复,
     收到回复后,再发下一个请求报文。*/
  char buffer[1024];
  for (int ii=0;ii<3;ii++)  // 循环3次,将与服务端进行三次通讯。
  {
    int iret;
    memset(buffer,0,sizeof(buffer));
    sprintf(buffer,"这是第%d个超级女生,编号%03d。",ii+1,ii+1);  // 生成请求报文内容。
    // 向服务端发送请求报文。
    if ( (iret=send(sockfd,buffer,strlen(buffer),0))<=0)
    { 
      perror("send"); break; 
    }
    cout << "发送:" << buffer << endl;
 
    memset(buffer,0,sizeof(buffer));
    /* 接收服务端的回应报文,如果服务端没有发送回应报文,recv()函数将阻塞等待。*/
    if ( (iret=recv(sockfd,buffer,sizeof(buffer),0))<=0)
    {
       cout << "iret=" << iret << endl; break;
    }
    cout << "接收:" << buffer << endl;
 
    sleep(1);
  }

通过一个循环,发送三次请求报文给服务端,每次发送后等待服务端的回复。发送和接收都使用send()recv()函数,如果发送或接收失败则跳出循环。

这段程序是用来与服务端进行通讯的,具体作用如下:

  • char buffer[1024];
    声明一个长度为1024的字符数组 buffer,用来存储通讯的数据。
  • for (int ii = 0; ii < 3; ii++)
    循环3次,每次循环代表与服务端进行一次通讯。
  • memset(buffer, 0, sizeof(buffer));
    清空 buffer 数组,以确保没有之前的残留数据。
  • sprintf(buffer, "这是第%d个超级女生,编号%03d。", ii + 1, ii + 1);
    使用 sprintf() 函数将字符串格式化写入 buffer 数组,形成一个请求报文的内容。
  • if ((iret = send(sockfd, buffer, strlen(buffer), 0)) <= 0)
    通过 send() 函数将请求报文发送给服务端,如果发送失败则输出错误信息,并跳出循环。
  • cout << "发送:" << buffer << endl;
    输出发送的请求报文内容。
  • memset(buffer, 0, sizeof(buffer));
    清空 buffer 数组,以便接收服务端的回应。
  • if ((iret = recv(sockfd, buffer, sizeof(buffer), 0)) <= 0)
    通过 recv() 函数接收服务端的回应报文,如果接收失败或接收到的字节数为0则跳出循环。
  • cout << "接收:" << buffer << endl;
    输出接收到的服务端的回应报文内容。
  • sleep(1);
    程序暂停1秒钟,然后进行下一次通讯。

4.关闭socket

  /* 第4步:关闭socket,释放资源。*/
  close(sockfd);

close()函数用于关闭客户端套接字,释放资源。


🌷4.2 服务端程序

server.cpp是一个简单的服务端程序,用于与服务器进行通讯。让我们分步来看:

命令行参数检查

  if (argc!=2)
  {
    cout << "Using:./server 通讯端口\nExample:./server 5005\n\n";   // 端口大于1024,不与其它的重复。
    cout << "注意:运行服务端程序的Linux系统的防火墙必须要开通5005端口。\n";
    cout << "      如果是云服务器,还要开通云平台的访问策略。\n\n";
    return -1;
  }

首先,程序检查命令行参数数量是否为2,如果不是,则输出使用说明并退出程序。

在运行命令 ./server 2003 时,命令行参数如下:

  • ./server:表示程序名称。
  • 2003:表示通讯端口,即服务端程序将在2003端口上进行通讯。

1.创建服务端的socket

  // 第1步:创建服务端的socket。 
  int listenfd = socket(AF_INET,SOCK_STREAM,0);
  if (listenfd==-1) 
  { 
    perror("socket"); return -1; 
  }

这段代码的作用是创建服务端的套接字(socket),并进行创建的错误检查。

  • int listenfd = socket(AF_INET, SOCK_STREAM, 0);这行代码创建了一个套接字,其中:
  • AF_INET指定了套接字的地址族为IPv4。
  • SOCK_STREAM指定了套接字的类型为流式套接字,即TCP套接字,它提供了可靠的、双向的、基于连接的字节流。
  • 0表示使用默认的协议。
  • if (listenfd == -1)
    这个条件判断检查套接字是否创建成功。如果套接字创建失败,socket() 函数返回 -1,程序通过 perror("socket") 输出相关错误信息,然后返回 -1 表示程序执行失败。

2.绑定IP地址和端口

  // 第2步:把服务端用于通信的IP和端口绑定到socket上。 
  struct sockaddr_in servaddr;          // 用于存放服务端IP和端口的数据结构。
  memset(&servaddr,0,sizeof(servaddr));
  servaddr.sin_family = AF_INET;        // 指定协议。
  servaddr.sin_addr.s_addr = htonl(INADDR_ANY); // 服务端任意网卡的IP都可以用于通讯。
  servaddr.sin_port = htons(atoi(argv[1]));     // 指定通信端口,普通用户只能用1024以上的端口。
  // 绑定服务端的IP和端口。
  if (bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr)) != 0 )
  { 
    perror("bind"); close(listenfd); return -1; 
  }

这段代码的作用是将服务端用于通信的IP地址和端口绑定到先前创建的套接字上。让我们逐步解析:

  • struct sockaddr_in servaddr;
    声明一个 sockaddr_in 结构体变量 servaddr,用于存放服务端IP地址和端口号的信息。
  • memset(&servaddr, 0, sizeof(servaddr));
    使用 memset() 函数将 servaddr 结构体清零,以确保没有之前的残留数据。
  • servaddr.sin_family = AF_INET;
    设置 servaddr 结构体中的地址族为 IPv4。
  • servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr 结构体中的IP地址设置为 INADDR_ANY,表示服务端可以使用任意可用的网络接口。
  • servaddr.sin_port = htons(atoi(argv[1]));
    将命令行参数中的通信端口号转换成整数并转换成网络字节序(大端序),然后存放在 servaddr 结构体中的 sin_port 字段。
  • if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0 )
    通过 bind() 函数将服务端IP地址和端口号与套接字进行绑定。如果绑定失败,输出错误信息,关闭套接字 listenfd,然后返回 -1 表示程序执行失败。

3.设置监听状态

  // 第3步:把socket设置为可连接(监听)的状态。
  if (listen(listenfd,5) != 0 ) 
  { 
    perror("listen"); close(listenfd); return -1; 
  }

这段代码的作用是将套接字设置为可连接(监听)的状态,以便服务端可以接受客户端的连接请求。

  • listen(listenfd, 5)
    调用 listen() 函数将套接字 listenfd 设置为监听状态,并指定了可以同时处理的连接请求的最大数量为5。这意味着在任何时刻,服务器最多可以处理5个等待连接的客户端请求。
  • if (listen(listenfd, 5) != 0 )
    检查 listen() 函数是否执行成功,如果不成功,输出错误信息,关闭套接字 listenfd,然后返回 -1 表示程序执行失败。

设置套接字为监听状态后,服务端将能够接受客户端的连接请求,并把这些请求放入队列中等待处理。

4.接受客户端连接请求

  // 第4步:受理客户端的连接请求,如果没有客户端连上来,accept()函数将阻塞等待。
  int clientfd=accept(listenfd,0,0);
  if (clientfd==-1)
  {
    perror("accept"); close(listenfd); return -1; 
  }
 
  cout << "客户端已连接。\n";

使用 accept() 函数受理客户端的连接请求,如果没有客户端连接上来,该函数将阻塞等待。

这段代码的作用是接受客户端的连接请求。让我们逐步解释:

  • int clientfd = accept(listenfd, 0, 0);
    调用 accept() 函数接受客户端的连接请求。参数 listenfd 是之前通过 socket()bind() 函数创建并绑定的监听套接字。函数会在有客户端连接请求到达时返回一个新的套接字 clientfd,用于与该客户端进行通信。
  • if (clientfd == -1)
    检查 accept() 函数是否成功接受客户端连接。如果返回值为 -1,表示发生了错误,通常是由于连接请求被拒绝或者出现了其他错误。在这种情况下,程序会输出错误信息,关闭监听套接字 listenfd,然后返回 -1 表示程序执行失败。
  • cout << "客户端已连接。\n";
    如果 accept() 成功接受了客户端的连接请求,程序会输出一条消息表示客户端已经连接上了。

综上所述,这段代码的作用是接受客户端的连接请求,并在成功连接时输出一条提示消息。

6.与客户端通信

  // 第5步:与客户端通信,接收客户端发过来的报文后,回复ok。
  char buffer[1024];
  while (true)
  {
    int iret;
    memset(buffer,0,sizeof(buffer));
    // 接收客户端的请求报文,如果客户端没有发送请求报文,recv()函数将阻塞等待。
    // 如果客户端已断开连接,recv()函数将返回0。
    if ( (iret=recv(clientfd,buffer,sizeof(buffer),0))<=0) 
    {
       cout << "iret=" << iret << endl;  break;   
    }
    cout << "接收:" << buffer << endl;
 
    strcpy(buffer,"ok");  // 生成回应报文内容。
    // 向客户端发送回应报文。
    if ( (iret=send(clientfd,buffer,strlen(buffer),0))<=0) 
    { 
      perror("send"); break; 
    }
    cout << "发送:" << buffer << endl;
  }

在一个循环中,不断接收客户端发送的请求报文,并回复 "ok"。

  • 使用 recv() 函数接收客户端的请求报文,如果接收失败或客户端断开连接,则跳出循环。
  • 使用 send() 函数向客户端发送回应报文。

这段代码是服务端与客户端进行通信的部分:

  • char buffer[1024];
    声明一个长度为1024的字符数组 buffer,用于存储通讯的数据。
  • while (true)
    进入一个无限循环,持续与客户端进行通信,直到客户端断开连接或发生错误。
  • memset(buffer, 0, sizeof(buffer));
    清空 buffer 数组,以确保没有之前的残留数据。
  • if ((iret = recv(clientfd, buffer, sizeof(buffer), 0)) <= 0)
    通过 recv() 函数接收客户端发送的请求报文,如果接收失败或客户端断开连接,则跳出循环。iret 变量存储接收到的字节数。
  • cout << "接收:" << buffer << endl;
    输出接收到的客户端请求报文内容。
  • strcpy(buffer, "ok");
    将回应报文内容设置为 "ok",表示服务端已接收到客户端的请求。
  • if ((iret = send(clientfd, buffer, strlen(buffer), 0)) <= 0)
    通过 send() 函数向客户端发送回应报文,如果发送失败,则输出错误信息,并跳出循环。
  • cout << "发送:" << buffer << endl;
    输出发送的回应报文内容。

总体来说,这段代码实现了一个服务端与客户端的简单通信过程。服务端不断接收客户端发送的请求报文,然后回复 "ok" 表示已收到。

7.关闭socket,释放资源

  // 第6步:关闭socket,释放资源。
  close(listenfd);   // 关闭服务端用于监听的socket。
  close(clientfd);   // 关闭客户端连上来的socket。

这段代码的作用是关闭套接字并释放相关资源

  • close(listenfd);
    关闭服务端用于监听客户端连接请求的套接字 listenfd。一旦服务端不再需要监听新的连接请求,可以关闭这个套接字,以释放相关资源并告知操作系统不再维护该套接字的状态信息。
  • close(clientfd);
    关闭客户端连接的套接字 clientfd。一旦服务端与客户端的通信结束,可以关闭这个套接字,释放相关资源,并结束与该客户端的通信。

通过关闭套接字,程序能够清理掉所占用的系统资源,并确保程序的正常结束。



目录
相关文章
用MASM32按Time Protocol(RFC868)协议编写网络对时程序中的一些有用的函数代码
用MASM32按Time Protocol(RFC868)协议编写网络对时程序中的一些有用的函数代码
|
24天前
|
Java
[Java]Socket套接字(网络编程入门)
本文介绍了基于Java Socket实现的一对一和多对多聊天模式。一对一模式通过Server和Client类实现简单的消息收发;多对多模式则通过Server类维护客户端集合,并使用多线程实现实时消息广播。文章旨在帮助读者理解Socket的基本原理和应用。
20 1
|
30天前
|
算法 数据挖掘 Shell
「毅硕|生信教程」 micromamba:mamba的C++实现,超越conda
还在为生信软件的安装配置而烦恼?micromamba(micromamba是mamba包管理器的小型版本,采用C++实现,具有mamba的核心功能,且体积更小,可以脱离conda独立运行,更易于部署)帮你解决!
58 1
|
1月前
|
存储 C++
c++的指针完整教程
本文提供了一个全面的C++指针教程,包括指针的声明与初始化、访问指针指向的值、指针运算、指针与函数的关系、动态内存分配,以及不同类型指针(如一级指针、二级指针、整型指针、字符指针、数组指针、函数指针、成员指针、void指针)的介绍,还提到了不同位数机器上指针大小的差异。
38 1
|
1月前
|
Linux C语言 C++
vsCode远程执行c和c++代码并操控linux服务器完整教程
这篇文章提供了一个完整的教程,介绍如何在Visual Studio Code中配置和使用插件来远程执行C和C++代码,并操控Linux服务器,包括安装VSCode、安装插件、配置插件、配置编译工具、升级glibc和编写代码进行调试的步骤。
211 0
vsCode远程执行c和c++代码并操控linux服务器完整教程
|
2月前
|
网络协议 开发者 Python
网络编程小白秒变大咖!Python Socket基础与进阶教程,轻松上手无压力!
在网络技术飞速发展的今天,掌握网络编程已成为开发者的重要技能。本文以Python为工具,带你从Socket编程基础逐步深入至进阶领域。首先介绍Socket的概念及TCP/UDP协议,接着演示如何用Python创建、绑定、监听Socket,实现数据收发;最后通过构建简单的聊天服务器,巩固所学知识。让初学者也能迅速上手,成为网络编程高手。
74 1
|
1月前
|
安全 网络协议 IDE
使用Python编写网络扫描程序
使用Python编写网络扫描程序
|
1月前
|
网络协议 测试技术 网络安全
Python编程-Socket网络编程
Python编程-Socket网络编程
|
3月前
|
存储 网络协议 安全
|
3月前
|
网络协议 Java
一文讲明TCP网络编程、Socket套接字的讲解使用、网络编程案例
这篇文章全面讲解了基于Socket的TCP网络编程,包括Socket基本概念、TCP编程步骤、客户端和服务端的通信过程,并通过具体代码示例展示了客户端与服务端之间的数据通信。同时,还提供了多个案例分析,如客户端发送信息给服务端、客户端发送文件给服务端以及服务端保存文件并返回确认信息给客户端的场景。
一文讲明TCP网络编程、Socket套接字的讲解使用、网络编程案例