iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++项目实战-socket编程
  • 169
分享到

C++项目实战-socket编程

网络服务器tcp/ipc++linux 2023-09-10 22:09:58 169人浏览 八月长安
摘要

目录 socket套接字概念 字节序 网络字节序 socket地址 通用socket地址 专用socket地址 IP转换址转换函数  网络套接字函数 socket模型创建流程图(TCP通信流程/CS模型流程图) 出错处理封装函数 Soc

目录

socket套接字概念

字节序

网络字节序

socket地址

通用socket地址

专用socket地址

IP转换址转换函数 

网络套接字函数

socket模型创建流程图(TCP通信流程/CS模型流程图)

出错处理封装函数


Socket套接字概念

        所谓套接字,就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。

一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。从所处的地位来讲,套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议进程通信的接口,是应用程序与网络协议进行交互的接口。

        它是网络环境中进行通信的api,使用中每一个套接字都有一个与之相连进程。通信时其中一个网络应用程序将要传输的一段信息写入他所在的主机socket中,该socket通过与网络接口卡(NIC)相连的传输介质将这段信息送到另一台主机的socket中,使对方能够接收到这段信息socket是由IP地址和端口结合的,提供应用层进程传送数据包的机制。

        socket本意上“插座”的意思,在linux环境中,用于表示进程间网络通信的特殊文件类型。本质上为内核借助缓冲区形成的伪文件。把它设置为文件,方便我们进行操作,我们可以通过文件描述符进行操作。与管道类型,Linux系统将期封装成文件的目的是为了统一接口,使得读写套接字和读写文件操作一样。区别是管道应用于本地进程间通信,而套接字多用于网络进程间数据的传递。

        socket是全双工通信,即在同一时刻既可以数据读入,也可以数据输出。

Mac地址(物理地址)

IP地址(逻辑地址): 在网络中唯一标识一台主机

端口号:在一台主机中唯一标识一个进程

IP+端口号:在网络环境中唯一标识一个进程

       

套接字原理:(绑定了IP和端口号)

在网络中套接字一定是成对出现的。

tcp/IP协议最早在BSD UNIX上实现,为TCP/IP协议设计的应用层编程接口称为socket API。 

-服务器端:被动接受连接,一般不会主动发起连接

-客户端:主动向服务器发起连接     

字节序

现在CPU的累加器一次都能装载(至少)4个字节(32位机),即一个整数。哈哈,我在想32位下指针也是4个字节,设定指针的大小与能够寻址范围有关,累加器的装载量限制了指针的大小和寻址范围。那么这4个字节在内存中排列的顺序将影响它被累加器装载的整数值,这就是字节序问题。在各种计算机体系结构中,对于字节、字等的存储机制有所不同,因而引发了计算机通信领域中一个很重要的问题,即通信双方交流的信息单元应该以什么样的顺序进行传送。如果不达成一致的规则,通信双方将无法进行正确的编码/译码从而导致通信失败。

(总而言之:字节序就是存储数据的方式,大家按照统一的规则进行,保证数据传输的正确性)

字节序分为大端字节序(Big-Endian)和小端字节序(Little-Endian)。大端字节序是指一个整数的高位字节存储在内存的低地址位置,低位字节存储在内存的高地址位置。小端字节序则是指一个整数的高位字节存储在内存高地址处,而低位字节则存储在内存的低地址处。

大端:低地址---高位

小端:高地址---低位

记忆方法: 低址对高位为大   高址对低位为小

网络字节序

        当格式化的数据在两台使用不同字节序的主机之间直接传递时,接收端必然会解释错误。那么怎么解决这个问题呢?假设我们让发送数据的一端总是以大端字节序发送(对就是做一个统一的规定),那么接收数据的一端就知道我接受到的字节序总是大端字节序,如果接受方的字节序为小端,那么只需要大端数据装换成小端字节序就可以了。

        TCP/IP协议中规定,网络数据流应采用大端字节序。

        

为了使用方便和移植性,我们可以调用相应的库函数进行转换...

h - host 主机,主机字节序

to 转换成什么

n - network 网络字节序

s - short unsigned short                端口

l - long unsigned int                       IP

#include

// 转换端口

uint16_t htons(uint16_t hostshort);                // 主机字节序 - 网络字节序

uint16_t ntohs(uint16_t netshort);                  // 主机字节序 - 网络字节序

// 转IP

uint32_t htonl(uint32_t hostlong);                   // 主机字节序 - 网络字节序

uint32_t ntohl(uint32_t netlong);                    // 主机字节序 - 网络字节序

测试下我本机的字节序吧,嘻嘻

#include #include //先定义一个联合体uNIOn{    int     number;    char    c;}test;//为什么用这个联合体可以测试呢?int main(void){    test.number = 0x12345678;    if(test.c == 0x12)  //高位存储在内存的低地址上    {        printf("本机为大端字节序\n");    }    else    {        printf("本机为小端字节序\n");    }    return 0;}

socket地址

        socket地址其实是一个结构体,封装端口和IP等信息。后面的socket相关的api中需要使用到这个socket地址。

        之前有说到过,socket套接字上联应用程序,下联协议栈

        对一个一个数据包想要在网络中的两台不同主机间的进程(当然我们这里不包括本地套接字),只要确认了对方IP(逻辑地址)和端口就可以将数据传送给对方【MAC地址可以根据ARP协议获取到】

通用socket地址

socket网络编程接口中表示socket地址是结构体sockaddr,其定义如下:

#include

struct sockaddr{                                //已经被废弃掉

        sa_family_t         sa_family;

        char                    sa_data[14];

};

typedef unsigned short int sa_family_t;

成员:

        sa_family成员是地址族类型(sa_family_t)的变量。地址族类型通常与协议类型对应。常见的协议族和对应的地址族如下所示:

协议族地址族描述
PF_UNIXAF_UNIXUNIX本地域协议族
PF_INETAF_INETTCP/IPv4协议族
PF_INET6AF_INET6TCP/IPv6协议族

协议族 PF_*和地址族AF_*在头文件bits/socket.h中,二者值相同,可以混合使用(反正都是宏定义,宏定义是预处理阶段进行宏替换,所以混着用对编译运行不会有影响)

其实我们很容易看到一个问题,

这个地方使用的是一个固定数  14type:

sa_data成员用于存放socket地址值。但是,不同的协议族的地址值具有不同的含义和长度

我们可以看到,14个字节几乎只能装下 IPv4地址。因此,Linux定义了下面这个新的通用的socket地址结构体,这个结构体不仅提供了足够大的空间用于存放地址值,而且是内存对齐的【内存对齐可以加快CPU访问速度,内存对齐问题见我的C语言专栏,有详细介绍】 

这个结构体定义在:/usr/include/linux/in.h

为了方便理解,我们去掉一些杂乱的信息:

#include struct sockaddr_storage{sa_family_t sa_family;unsigned long int __ss_align;char __ss_padding[ 128 - sizeof(__ss_align) ];};typedef unsigned short int sa_family_t;

专用socket地址

很多网络编程函数诞生早于IPv4协议(用自定义的协议咯,双方共同约定一个规则),那时候都是使用struck socketaddr结构体,为了向前兼容,现在在socketaddr退化成了 (void *)的作用,传递一个地址给函数,至于这个函数是sockaddr_in还是sockaddr_in6,由地址族确定,然后函数内部再强制类型转化为所需的地址类型

 UNIX 本地域协议族使用如下专用的 socket 地址结构体:

#include struct sockaddr_un{sa_family_t sin_family;char sun_path[108];};

TCP/IP 协议族有 sockaddr_in 和 sockaddr_in6 两个专用的 socket 地址结构体,它们分别用于 IPv4 和 IPv6:

#include struct sockaddr_in{sa_family_t sin_family; in_port_t sin_port; struct in_addr sin_addr; unsigned char sin_zero[sizeof (struct sockaddr) - __SOCKADDR_COMMON_SIZE -sizeof (in_port_t) - sizeof (struct in_addr)];};struct in_addr{in_addr_t s_addr;};struct sockaddr_in6{sa_family_t sin6_family;in_port_t sin6_port; uint32_t sin6_flowinfo; struct in6_addr sin6_addr; uint32_t sin6_scope_id; };typedef unsigned short uint16_t;typedef unsigned int uint32_t;typedef uint16_t in_port_t;typedef uint32_t in_addr_t;#define __SOCKADDR_COMMON_SIZE (sizeof (unsigned short int))

所有专用 socket 地址(以及 sockaddr_storage)类型的变量在实际使用时都需要转化为通用 socket 地 址类型 sockaddr(强制转化即可),因为所有 socket 编程接口使用的地址参数类型都是 sockaddr。

IP转换址转换函数 

人们习惯用可读性好的字符串来表示IP地址,比如用点分十进制字符串表示IPV4地址,以及用十六进制字符串表示IPv6地址,但编程中我们需要先把他们转化为整数(二进制)方能使用。而记录日志相反,我们需要把整数表示的IP地址转化为可读的字符串。

早期:(不推荐使用)

#include

#include

#include

int inet_aton(const char *cp,struct in_addr *inp);

in_addr_t  inet_addr(const char *cp);

char *inet_ntoa(struct in_addr in);         

这只能处理IPV4的ip地址,不可重入函数

现在:

p:点分十进制的IP字符串

n:表示network,网络字节序的整数

#include 

int inet_pton(int af,const char *src,void *dst);

af:地址族: AF_INET AF_INET6

src:需要转换的点分十进制的IP字符串

dst:转换后的结果保存在这个里面

const char *inet_ntop(int af,const void *src,char *dst,socklen_t size);

af:AF_INET   AF_INE6

src: 要转换的ip的整数的地址

dst: 转换成IP地址字符串保存的地方

size:第三个参数的大小(数组的大小)

返回值:返回转换后的数据的地址(字符串),和 dst 是一样的

点分十进制 --->  网络字节序   inet_pton

网络字节序 --->  点分十进制   inet_ntop

网络套接字函数

socket模型创建流程图(TCP通信流程/CS模型流程图)

头文件:#include

或者:#include     #include

int socket(int domain,int type,int protocol);

功能:创建一个套接字

参数:

        domain:协议族

                AF_INET   -->  ipv4

                AF_INET6 -->  ipv6

                AF_UNIX  AF_LOCAL  --> 本地套接字通信(进程间通信)

        type:通信过程中使用的协议协议

                SOCK_STREAM --> 流式协议

                SOCK_DGRAM   --> 报式文件

        protocol:具体的一个协议,一般写 0

                SOCK_STREAM  --> 流式文件默认使用 TCP

                SOCK_DGRAM    --> 报式文件默认使用 UDP

返回值:

        成功:返回文件描述符,操作的就是内核缓冲区(socket本质上是一个伪文件)

        失败:-1

int bind(int sockfd,const struct sockaddr *addr,socklen_t addrlen);

功能:绑定,将fd和本地的IP+端口进行绑定

参数:

            sockfd:通过socket函数得到的文件描述符

            addr:需要绑定的socket地址,这个地址封装了ip和端口号的信息

            addrlen:第二个参数结构体占的内存大小

int listen(int sockfd,int backlog);

功能:监听这个socket上的连接

参数:

           sockfd:通过socket()函数得到的文件描述符

            backlog:未连接的和、已连接的和的最大值        5

int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen);

功能:接收客户端连接,默认是一个阻塞的函数,阻塞等待客户端连接

参数:

           sockfd:用于监听的文件描述符

           addr:传出参数,记录连接成功后客户端的地址信息(ip、port)

           addrlen:指定第二个参数的对应的内存大小

返回值:

        成功:用于通信的文件描述符

        失败:-1

ssize_t write(int fd, const void *buf, size_t count); // 写数据

ssize_t read(int fd, void *buf, size_t count); // 读数据

上个程序案例

#include #include #include #include #include //定义IP#define SERVER_IP   "127.0.0.1"//定义端口#define SERVER_PORT  8080int main(void){    int lfd,cfd;    char str[INET_ADDRSTRLEN];    //创建socket套接字    lfd = socket(AF_INET,SOCK_STREAM,0);  //TCP  ipv4    //绑定 IP(server) 和 端口号(监听)    struct sockaddr_in serverAddr;    memset(&serverAddr,0,sizeof(serverAddr));    serverAddr.sin_family = AF_INET;    serverAddr.sin_port = htons(SERVER_PORT);    serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);  //或者 INADDR_ANY:提供任意一个本地有效IP    bind(lfd,(struct sockaddr *)&serverAddr,sizeof(serverAddr));    //监听 设置最大监听数目 128    listen(lfd,128);    //等待连接    struct sockaddr_in clientAddr;    socklen_t clientAddr_len = sizeof(clientAddr);    cfd = accept(lfd,(struct sockaddr *)&clientAddr,&clientAddr_len);     //数据交换    int n,i=0;    char buf[1024] = {0};    while(1)    {             n = read(cfd,buf,sizeof(buf));        if(n == 0)  //有客户端断开连接        {            printf("有客户端断开连接\n");        }        if(n < 0)        {            printf("aaaaaaaa\n");        }        // inet_ntop(AF_INET,&clientAddr.sin_addr,str,sizeof(str));        // ntohs(clientAddr.sin_port);        printf("已收到第%d次数据:%s\n",i++,buf);        //sleep(2);        write(cfd,buf,n);    }       close(cfd);    close(lfd);    return 0;}
#include #include #include #include #include //定义IP#define SERVER_IP   "127.0.0.1"// //定义端口#define SERVER_PORT  8080int main(void){    int sockfd;    //创建套接字  TCP ipv4    sockfd = socket(AF_INET,SOCK_STREAM,0);     //连接    struct sockaddr_in serverAddr;    memset(&serverAddr,0,sizeof(serverAddr));    serverAddr.sin_family = AF_INET;    serverAddr.sin_port = htons(SERVER_PORT);    inet_pton(AF_INET,SERVER_IP,&serverAddr.sin_addr);    connect(sockfd,(struct sockaddr *)&serverAddr,sizeof(serverAddr));    //数据交换    char buf[1024] = {0};    int i=0,n=0;    while(1)    {        //memset(buf,0,sizeof(buf));        fgets(buf,sizeof(buf),stdin);        //scanf("%s",buf);        write(sockfd,buf,sizeof(buf));        memset(buf,0,sizeof(buf));        n = read(sockfd,buf,sizeof(buf));        printf("------a-------\n");        write(STDOUT_FILENO,buf,n);    }    close(sockfd);    return 0;}

客户端与服务器端启动连接后可以使用 netstat -apn|grep 8080查看连接情况

出错处理封装函数

        我们知道,系统调用不能保证每次都成功,必须进行错误处理,这样一方面可以保证程序的逻辑正常,另一方面可以迅速得到故障信息。

        为使错误处理的代码不影响主程序的可读性,我们把与socket相关的一系列函数加上错误代码封装成新的函数(按照系统的库函数进行封装),做成一个模板 wrap.c

 如果有需要,请把这份代码自己保存好,下次可以直接使用.(有兴趣的可以打包成动态库)

        

先来把头文件搞定:

先来看下我们需要定义哪些东西:其实很简单,其实并不难。先把框架搭起来。欧里给

对呀,就上面这些系统调用,直接粘过来,把每一个都一个错误处理的接口API.  搞定

函数名直接取,最好按驼峰法取名

#ifndef _WRAP_H_#define _WRAP_H_void perr_exit(const char *s);int  Accept(int fd,struct sockaddr *sa,socklen_t *salenptr);int  Bind(int fd,const struct sockaddr *sa,socklen_t salen);int  Connect(int fd,const struct sockaddr *sa,socklen_t salen);int  Listen(int fd,int backlog);int  Socket(int family,int type,int protocol);ssize_t Read(int fd,void *ptr,size_t nbytes);ssize_t Write(int fd,const void *ptr,size_t nbytes);int Close(int fd);ssize_t Readn(int fd,void *vptr,size_t n);ssize_t Writen(int fd,const void *vptr,size_t n);ssize_t my_read(int fd,char *ptr);ssize_t Readline(int fd,void *vptr,size_t maxlen); #endif

 

#include #include #include #include #include #include void perr_exit(const char *s){    perror(s);    exit(1);}int  Accept(int fd,struct sockaddr *sa,socklen_t *salenptr){    int n;     //accept:阻塞,是慢系统调用。可能会被信息中断    again:    if((n = accept(fd,sa,salenptr)) < 0)    {        if((errno == ECONNABORTED) || (errno == EINTR))        {            Goto again;   //重启        }        else        {            perr_exit("accept error");        }    }    return n;}int  Bind(int fd,const struct sockaddr *sa,socklen_t salen){    int n;    if((n = bind(fd,sa,salen)) < 0)    {        perr_exit("bind error");    }    return n;}int  Connect(int fd,const struct sockaddr *sa,socklen_t salen){    int n;    if((n = connect(fd,sa,salen)) < 0)    {        perr_exit("connect error");    }    return n;}int  Listen(int fd,int backlog){    int n;    if((n = listen(fd,backlog)) < 0)    {        perr_exit("listen error");    }    return n;}int  Socket(int family,int type,int protocol){    int n;    if((n = socket(family,type,protocol)) < 0)    {        perr_exit("socket error");    }    return n;}ssize_t Read(int fd,void *ptr,size_t nbytes){    ssize_t n;    again:    if((n = read(fd,ptr,nbytes)) == -1)    {        if(errno == EINTR)//被中断        {            goto again;        }        else        {            return -1;        }    }    return n;}ssize_t Write(int fd,const void *ptr,size_t nbytes){    ssize_t n;    again:    if((n = write(fd,ptr,nbytes)) == -1)    {        if(errno == EINTR)        {            goto again;        }        else        {            return -1;        }    }    return n;}int Close(int fd){    int n;    if((n = close(fd)) == -1)    {        perr_exit("close error");    }    return n;}ssize_t Readn(int fd,void *vptr,size_t n){    size_t nleft;    ssize_t nread;    char *ptr;    ptr = vptr;    nleft = n;    while(nleft > 0)    {        if((nleft = read(fd,ptr,nleft)) < 0)        {           if(errno == EINTR)           {                nread = 0;           }           else           {                return -1;           }        }        else if(nread == 0)        {            break;        }        nleft -= nread;        ptr += nread;    }    return n-nleft;}ssize_t Writen(int fd,const void *vptr,size_t n){    size_t nleft;    ssize_t nwritten;    const char *ptr;    ptr = vptr;    nleft = n;    while(nleft > 0)    {        if((nwritten = write(fd,ptr,nleft)) <= 0)        {            if(nwritten < 0 && errno == EINTR)            {                nwritten = 0;            }            else            {                return -1;            }        }        nleft -= nwritten;        ptr += nwritten;    }    return n;}static ssize_t my_read(int fd,char *ptr){    static int read_cnt;    static char *read_ptr;    static char read_buf[100];    if(read_cnt <= 0)    {        again:            if((read_cnt = read(fd,read_buf,sizeof(read_buf))) < 0)            {                if(errno == EINTR)                {                    goto again;                }                return -1;            }            else if(read_cnt == 0)            {                return 0;            }            read_ptr = read_buf;    }    read_cnt--;    *ptr = *read_ptr++;    return 1;}ssize_t Readline(int fd,void *vptr,size_t maxlen){    ssize_t n,rc;    char c,*ptr;    ptr = vptr;    for(n=1;n

     

来源地址:https://blog.csdn.net/weixin_46120107/article/details/126528923

--结束END--

本文标题: C++项目实战-socket编程

本文链接: https://www.lsjlt.com/news/402667.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C++项目实战-socket编程
    目录 socket套接字概念 字节序 网络字节序 socket地址 通用socket地址 专用socket地址 IP转换址转换函数  网络套接字函数 socket模型创建流程图(TCP通信流程/CS模型流程图) 出错处理封装函数 soc...
    99+
    2023-09-10
    网络 服务器 tcp/ip c++ linux
  • C++图形编程项目实战指南
    非常抱歉,由于您没有提供文章标题,我无法为您生成一篇高质量的文章。请您提供文章标题,我将尽快为您生成一篇优质的文章。...
    99+
    2024-05-15
  • Java协程编程之Loom项目实战记录
    目录前提Loom项目简单介绍Virtual Thread使用小结前提 之前很长一段时间关注JDK协程库的开发进度,但是前一段时间比较忙很少去查看OpenJDK官网的内容。Java协程...
    99+
    2024-04-02
  • C++项目实战-多进程(一篇文章)
    目录 目录 目录 程序和进程的基本概念 单道程序设计和多道程序设计 并行和并发 进程控制块PCB 进程常用的命令  环境变量 环境变量操作函数 进程控制 进程间通信(IPC方法) 程序和进程的基本概念 程序: 是指编译好的二进制文件...
    99+
    2023-10-21
    c++ servlet c语言 服务器
  • C++socket网络编程实战http服务器(支持php)(上)
    @TOC 第一章 Socket快速入门篇 1、TCP/IP模型 用Wireshark抓包工具来看一下上图TCP/IP模型这种4层协议里面究竟有什么内容。 在windows和Linux系...
    99+
    2023-09-02
    服务器 网络 c++ socket
  • C语言实现SOCKET编程
    以下是一个简单的C语言示例,演示了如何使用socket编程创建一个简单的服务器和客户端。在此示例中,服务器将侦听来自客户端的消息并将...
    99+
    2023-09-27
    c语言
  • C#网络编程之Socket编程
    目录一:什么是SOCKET套接字分类二:SOCKET相关概念1、端口2、协议2.1 TCP:2.2 UDP三:socket一般应用模式:四:SOCKET通信基本流程图:服务器端:客户...
    99+
    2024-04-02
  • 详谈C++ socket网络编程实例
    目录功能源码效果总结 功能 实现基于sokcet的Cpp服务端 TIPS:功能包括接收客户端的数据,向客户端发送数据。 源码 #define _WINSOCK_DEPRECA...
    99+
    2024-04-02
  • C++实现通讯录系统项目实战
    本文实例为大家分享了C++实现通讯录系统项目的具体代码,供大家参考,具体内容如下 制作一个具有添加联系人、删除联系人、修改联系人等功能的通讯录系统 效果图: 代码如下: #incl...
    99+
    2024-04-02
  • Python 网络编程项目实战:打造在线游戏
    搭建服务端和客户端 首先,我们需要搭建游戏服务端和客户端。服务端负责游戏逻辑的处理,客户端负责游戏的图形界面和玩家输入的处理。 服务端 服务端可以使用 Python 的 socket 模块来实现。socket 模块提供了网络编程的基础函...
    99+
    2024-02-13
    Python 网络编程 在线游戏 多人游戏 游戏开发
  • Python 网络编程项目实战:打造多人聊天室
    1. 项目概述 本项目将构建一个多人聊天室,允许多个用户同时在线聊天。聊天室的功能包括: 用户可以登录聊天室。 用户可以发送和接收消息。 用户可以查看在线用户列表。 用户可以退出聊天室。 2. 技术栈 本项目将使用以下技术栈: P...
    99+
    2024-02-13
    Python 网络编程 聊天室 套接字编程 多线程处理
  • 详谈C++ socket网络编程实例(2)
    目录功能源码效果总结 功能 完成Cpp客户端简单功能,可收发数据。 Cpp服务端实例地址:【点击跳转】 源码 #define _WINSOCK_DEPRECATED_NO_W...
    99+
    2024-04-02
  • C++ Socket实现TCP与UDP网络编程
    目录前言TCP1). 服务器2). 客户端3). TCP聊天小项目UDP1). 服务器2). 客户端总结前言 socket编程分为TCP和UDP两个模块,其中TCP是可靠的、安全的,...
    99+
    2024-04-02
  • Qt项目实战之实现多文本编辑器
    首先先来看实验成果图,大概就是这么个多文档编辑器。 首先需要在设计模式里进行设计器的设置: 然后就是新建类MdiChild的声明和实现 mdichild.h #ifndef MD...
    99+
    2023-03-19
    Qt多文本编辑器 Qt文本编辑器 Qt编辑器
  • 微信小程序实战项目之富文本编辑器实现
    目录前言1. 实现效果2. 创建发布页面,实现基本布局3. 实现编辑区操作栏的功能3.1. 实现文本加粗、斜体、文本下划线、左对齐、居中对齐、右对齐3.2. 实现撤销、恢复、插入图片...
    99+
    2024-04-02
  • C#中的Socket编程详解
    目录一,网络基础二,Socket 对象SocketTypeProtocolTypeAddressFamily三,Bind() 绑定与 Connect() 连接Bind()Connec...
    99+
    2024-04-02
  • SpringBoot项目实战笔记:电脑商城项目实战(SpringBoot+MyBatis+MySQL)
    花了一段实现刚学完SpringBoot,做个项目练练手。教程视频来源于B站。 视频链接: 【SpringBoot项目实战完整版】SpringBoot+MyBatis+MySQL电脑商城项目实战_哔哩哔哩_bilibili 目录...
    99+
    2023-08-31
    spring boot mybatis mysql
  • C语言游戏项目球球大作战实现流程
    目录项目代码 1、结构体2、初始化3、绘制函数 4、玩家控制函数 5、吃食物函数6、电脑移动函数7、主函数总结序 时间在流去,我们在长大 嗨,这里是狐狸...
    99+
    2024-04-02
  • 人工智能实战项目(python)+多领域实战练手项目
    人工智能实战项目 大家好,我是微学AI,本项目将围绕人工智能实战项目进行展开,紧密贴近生活,实战项目设计多个领域包括:金融、教育、医疗、地理、生物、人文、自然语言处理等;帮助各位读者结合机器学习与深度学习构建智能而且实用的人工智能简单系统,...
    99+
    2023-09-08
    人工智能 深度学习 计算机视觉 知识图谱
  • python十个实战项目
    python项目练习一:即时标记 python项目练习二:画幅好画 python项目练习三:万能的XML python项目练习四:新闻聚合 python项目练习五:虚拟茶话会 python项目练习六:使用CGI进行远程编辑 python项...
    99+
    2023-01-31
    实战 项目 python
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作