C/C++socket编程

--------------| socket 使用与相关函数 |--------------

1. 服务端

a. 头文件

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>   
#define PORT 8888   // 定义端口
#define MAXLEN 1024  

b. 服务器设置流程

  1. 创建套接字,用以绑定本机ip并监听访问ip
// 创建一个用以监听的套接字,并设置类型,此时还没绑定ip和端口
int listenfd = socket(AF_INET,SOCK_STREAM,0);  // 成功返回非负数
  1. 绑定套接字
// socket绑定需要特定的套接字地址信息结构体,
// 有两种套接字地址信息结构体 sockaddr 和 sockaddr_in
// sockaddr 是sockaddr_in 的抽象,内部变量只有 af_family 和 port 两个
// sockaddr_in 是具体的地址信息结构体,针对 ipv4 专用的结构体
struct sockaddr_in serverAddr;
memset(&serverAddr,0,siezof(serverAddr));   // 结构体初始化,清 0
serverAddr.sin_family = AF_INET;        // 指定地址家族 ipv4
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);  // 本机所有地址,转网络字节序
serverAddr.sin_port = htons(PORT);           // 端口转网络字节序

// 将结构与监听套接字进行绑定,
// 处于函数通用性,bind()、listen()、accept()等函数
// 都用 struct sockaddr 的抽象结构体 成功返回 0 ,失败返回负数;
bind(listenfd,(struct sockaddr*)serverAddr,sizeof(serverAddr));

  1. 设置监听
// 使用listen()函数设置监听属性,将socket主动编程被动监听
// 成功返回 0 ,失败返回负数
listen(listenfd,5); // 第二个参数表示指定队列中最多可有的连接请求数
  1. 等待并接受其他主机的连接
// 接受客户端的连接,并返回客户端的socket句柄(文件描述符)
struct sockaddr_in clientAddr;
int clientfd = accept(listenfd,(struct sockaddr*)clientAddr,sizeof(clientAddr));   // 之后就是通过 clientfd 与客户端进行接收和发送消息
  1. 接受和发送数据信息
// 接受信息
char str[256];
int n = read(clientfd,str,sizeof(str));   // 读取网络数据到str,返回值为读取到的数量
// 发送信息
write(clitentfd,str,n); // 发送数据给 clientfd
  1. 结束服务并释放所有 socket句柄(文件描述符)
close(clientfd);    // 关闭客户端句柄
close(listenfd);    // 关闭服务器句柄

2. 客户端

a. 头文件

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>   
#define PORT 8888   // 定义端口
#define MAXLEN 1024  

b. 客户端设置流程

创建套接字 —> 连接服务器 —> 发送和接受数据

  1. 创建套接字
int socketfd;
socketfd = socket(AF_INET,SOCK_STREAM,0);    // 获取套接字句柄 成功返回非 0 
  1. 连接服务器
// 设置服务器信息
struct sockaddr_in serverAddr;
memset(&serverAddr,0,sizeof(serverAddr));
serverAddr.sin_family = AF_INET;   // 设置地址家族  ipv4
serverAddr.sin_port = htons(PORT);  // 设置端口
inet_pton(AF_INET,"192.168.1.8",&serverAddr.sin_addr);  // 指定ip转为网络字节序

// 连接服务器
connect(socketfd,(struct sockaddr*)serverAddr,sizeof(serverAddr));  // 连接服
// 通过socketfd实现数据的 接受 和 发送

  1. 数据的 发送 与 接收
// 发送数据
char str[256] = "发送的数据";
int sendN = write(socket,str,sizeof(str));  // 返回值为成功发送的个数
int recvN = read(socket,str,sizeof(str));   // 返回值为接收的数据个数  

write(STDOUT_FILENO, str, recvN); // 像标准输出设备输出接受的数量
  1. 释放相关句柄
close(socket);  // 释放文件描述符  linux下一切皆文件

-------------------|其他相关函数|-------------------

1. TCP连接相关函数

TCPIO读写
send()write()
recv()read()
send();     // 这两个函数可以作为write() 和 read() 的替代品
recv();     // 提供了更多的错误检查和控制选项,发送接受大小可以指定,
            // 还有一些发送接受的标志

2. UDP连接相关函数

发送接收
UDP连接sendto()recvfrom()
sendto();       // 发送数据是需要目标 ip 和 port 作为参数
recvfrom();     // 接受数据会返回发送方的 ip 和 port

3. 其他函数

其他socket函数poll()select()

poll()和select()函数是用于多路复用I/O操作的重要工具,它们允许一个进程同时监控多个文件描述符(如套接字、管道等)的状态变化,而无需实际读取或写入数据。这两种函数特别适合于需要处理大量并发连接的服务器应用程序,如Web服务器、代理服务器或聊天服务器等。

int poll(struct pollfd *fds, nfds_t nfds, int timeout);
/*
fds:一个struct pollfd数组的指针,用于指定监控的文件描述符及其状态变化。
nfds:数组fds中元素的数量。
timeout:指定阻塞等待的时间限制(毫秒为单位)。若为负数,则poll()将立即返回;若为0,则poll()不会阻塞,立即返回当前状态;若为正数,则poll()将在指定的时间内等待,超时后返回。

返回值:
    若有文件描述符变为就绪状态,则返回就绪的文件描述符个数。
    若超时,则返回0。
    若发生错误,则返回-1,并设置errno。
*/
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
/*
nfds:监控的最大文件描述符+1。
readfds:指向一个fd_set类型的指针,用于指定希望监控读就绪的文件描述符集合。
writefds:指向一个fd_set类型的指针,用于指定希望监控写就绪的文件描述符集合。
exceptfds:指向一个fd_set类型的指针,用于指定希望监控异常条件的文件描述符集合。
timeout:指向一个struct timeval类型的指针,用于指定阻塞等待的时间限制。如果timeout为NULL,则select()将无限期阻塞,直到有文件描述符变得可读、可写或发生异常;如果timeout为非零值,select()将在指定的时间内等待,超时后返回。

返回值:
    若有文件描述符变为就绪状态,则返回就绪的文件描述符个数。
    若超时,则返回0。
    若发生错误,则返回-1,并设置errno。
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值