【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。一旦服务端与客户端的通信结束,可以关闭这个套接字,释放相关资源,并结束与该客户端的通信。

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



目录
相关文章
|
29天前
|
开发者 Python
Python Socket编程:不只是基础,更有进阶秘籍,让你的网络应用飞起来!
在数字时代,网络应用成为连接世界的桥梁。Python凭借简洁的语法和丰富的库支持,成为开发高效网络应用的首选。本文通过实时聊天室案例,介绍Python Socket编程的基础与进阶技巧。基础篇涵盖服务器和客户端的建立与数据交换;进阶篇则探讨多线程与异步IO优化方案,助力提升应用性能。通过本案例,你将掌握Socket编程的核心技能,推动网络应用飞得更高、更远。
34 1
|
4天前
|
存储 程序员 编译器
简述 C、C++程序编译的内存分配情况
在C和C++程序编译过程中,内存被划分为几个区域进行分配:代码区存储常量和执行指令;全局/静态变量区存放全局变量及静态变量;栈区管理函数参数、局部变量等;堆区则用于动态分配内存,由程序员控制释放,共同支撑着程序运行时的数据存储与处理需求。
46 21
|
22天前
|
存储 机器人 Linux
Netty(二)-服务端网络编程常见网络IO模型讲解
Netty(二)-服务端网络编程常见网络IO模型讲解
|
22天前
|
C++
【C++基础】程序流程结构详解
这篇文章详细介绍了C++中程序流程的三种基本结构:顺序结构、选择结构和循环结构,包括if语句、三目运算符、switch语句、while循环、do…while循环、for循环以及跳转语句break、continue和goto的使用和示例。
21 2
|
26天前
|
网络协议 Python
网络世界的建筑师:Python Socket编程基础与进阶,构建你的网络帝国!
在数字宇宙中,网络如同复杂脉络连接每个角落,Python Socket编程则是开启这一世界的钥匙。本文将引导你从基础概念入手,逐步掌握Socket编程,并通过实战示例构建TCP/UDP服务器与客户端。你将学会使用Python的socket模块进行网络通信,了解TCP与UDP的区别,并运用多线程与异步IO提升服务器性能。跟随本文指引,成为网络世界的建筑师,构建自己的网络帝国。
29 2
|
27天前
|
网络协议 Python
告别网络编程迷雾!Python Socket编程基础与实战,让你秒变网络达人!
在网络编程的世界里,Socket编程是连接数据与服务的关键桥梁。对于初学者,这往往是最棘手的部分。本文将用Python带你轻松入门Socket编程,从创建TCP服务器与客户端的基础搭建,到处理并发连接的实战技巧,逐步揭开网络编程的神秘面纱。通过具体的代码示例,我们将掌握Socket的基本概念与操作,让你成为网络编程的高手。无论是简单的数据传输还是复杂的并发处理,Python都能助你一臂之力。希望这篇文章成为你网络编程旅程的良好开端。
43 3
|
26天前
|
网络协议 开发者 Python
网络编程小白秒变大咖!Python Socket基础与进阶教程,轻松上手无压力!
在网络技术飞速发展的今天,掌握网络编程已成为开发者的重要技能。本文以Python为工具,带你从Socket编程基础逐步深入至进阶领域。首先介绍Socket的概念及TCP/UDP协议,接着演示如何用Python创建、绑定、监听Socket,实现数据收发;最后通过构建简单的聊天服务器,巩固所学知识。让初学者也能迅速上手,成为网络编程高手。
59 1
|
8天前
|
JSON API 开发者
深入解析Python网络编程与Web开发:urllib、requests和http模块的功能、用法及在构建现代网络应用中的关键作用
深入解析Python网络编程与Web开发:urllib、requests和http模块的功能、用法及在构建现代网络应用中的关键作用
11 0
|
8天前
|
网络协议 测试技术 网络安全
Python编程-Socket网络编程
Python编程-Socket网络编程
15 0
|
21天前
|
网络协议
关于套接字socket的网络通信。&聊天系统 聊天软件
关于套接字socket的网络通信。&聊天系统 聊天软件