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

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



目录
相关文章
|
1月前
|
存储 数据可视化 API
重磅干货,免费三方网络验证[用户系统+CDK]全套API接口分享教程。
本套网络验证系统提供全面的API接口,支持用户注册、登录、数据查询与修改、留言板管理等功能,适用于不想自建用户系统的APP开发者。系统还包含CDK管理功能,如生成、使用、查询和删除CDK等。支持高自定义性,包括20个自定义字段,满足不同需求。详细接口参数及示例请参考官方文档。
|
1月前
|
Kubernetes 网络协议 Python
Python网络编程:从Socket到Web应用
在信息时代,网络编程是软件开发的重要组成部分。Python作为多用途编程语言,提供了从Socket编程到Web应用开发的强大支持。本文将从基础的Socket编程入手,逐步深入到复杂的Web应用开发,涵盖Flask、Django等框架的应用,以及异步Web编程和微服务架构。通过本文,读者将全面了解Python在网络编程领域的应用。
36 1
|
2月前
|
Java
[Java]Socket套接字(网络编程入门)
本文介绍了基于Java Socket实现的一对一和多对多聊天模式。一对一模式通过Server和Client类实现简单的消息收发;多对多模式则通过Server类维护客户端集合,并使用多线程实现实时消息广播。文章旨在帮助读者理解Socket的基本原理和应用。
33 1
|
2月前
|
消息中间件 监控 网络协议
Python中的Socket魔法:如何利用socket模块构建强大的网络通信
本文介绍了Python的`socket`模块,讲解了其基本概念、语法和使用方法。通过简单的TCP服务器和客户端示例,展示了如何创建、绑定、监听、接受连接及发送/接收数据。进一步探讨了多用户聊天室的实现,并介绍了非阻塞IO和多路复用技术以提高并发处理能力。最后,讨论了`socket`模块在现代网络编程中的应用及其与其他通信方式的关系。
276 3
|
2月前
|
网络协议 测试技术 网络安全
Python编程-Socket网络编程
Python编程-Socket网络编程
31 0
|
5月前
|
网络协议 开发者 Python
深度探索Python Socket编程:从理论到实践,进阶篇带你领略网络编程的魅力!
【7月更文挑战第25天】在网络编程中, Python Socket编程因灵活性强而广受青睐。本文采用问答形式深入探讨其进阶技巧。**问题一**: Socket编程基于TCP/IP,通过创建Socket对象实现通信,支持客户端和服务器间的数据交换。**问题二**: 提升并发处理能力的方法包括多线程(适用于I/O密集型任务)、多进程(绕过GIL限制)和异步IO(asyncio)。**问题三**: 提供了一个使用asyncio库实现的异步Socket服务器示例,展示如何接收及响应客户端消息。通过这些内容,希望能激发读者对网络编程的兴趣并引导进一步探索。
62 4
|
5月前
|
开发者 Python
Python Socket编程:不只是基础,更有进阶秘籍,让你的网络应用飞起来!
【7月更文挑战第25天】在网络应用蓬勃发展的数字时代,Python凭借其简洁的语法和强大的库支持成为开发高效应用的首选。本文通过实时聊天室案例,介绍了Python Socket编程的基础与进阶技巧,包括服务器与客户端的建立、数据交换等基础篇内容,以及使用多线程和异步IO提升性能的进阶篇。基础示例展示了服务器端监听连接请求、接收转发消息,客户端连接服务器并收发消息的过程。进阶部分讨论了如何利用Python的`threading`模块和`asyncio`库来处理多客户端连接,提高应用的并发处理能力和响应速度。掌握这些技能,能使开发者在网络编程领域更加游刃有余,构建出高性能的应用程序。
38 3
|
5月前
|
网络协议 Python
网络世界的建筑师:Python Socket编程基础与进阶,构建你的网络帝国!
【7月更文挑战第26天】在网络的数字宇宙中,Python Socket编程是开启网络世界大门的钥匙。本指南将引领你从基础到实战,成为网络世界的建筑师。
67 2
|
5月前
|
网络协议 程序员 视频直播
|
5月前
|
消息中间件 网络协议 网络安全
Python Socket编程:打造你的专属网络通道,基础篇与进阶篇一网打尽!
【7月更文挑战第26天】在网络编程领域,Python以简洁语法和强大库支持成为构建应用的首选。Socket编程为核心,实现计算机间的数据交换。
75 1