首页 > 代码库 > Socket基础编程
Socket基础编程
地址结构sockaddr_in
其中包含:IP地址,端口号,协议族
推荐使用sockaddr_in
,而不建议使用sockaddr
sockaddr_in
与sockaddr
是等价的,但sockaddr_in
字段更清晰
/* * Socket address, internet style. */struct sockaddr_in { __uint8_t sin_len; sa_family_t sin_family; in_port_t sin_port; struct in_addr sin_addr; char sin_zero[8];};
sockaddr_in字段描述
// 地址家族,通常使用AF_INET代表TCP/CP协议族(AF_INET6代表IPV6)sockaddr_in.sin_family// 端口号,必须转化为网络字节序使用htons和ntohssockaddr_in.sin_port// 用于存储ip地址,必须是网络字节序sockaddr_in.sin_addr// 为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节sockaddr_in.sin_zero
sockaddr_in字段初始化
struct sockaddr_in servaddr;bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(8090);// 若字符串有效则将字符串转换为32位二进制网络字节序的IPV4地址servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");// 检测转化IP是否出错if (servaddr.sin_addr.s_addr == INADDR_NONE) { perror("ip"); exit(-1);}
用到的函数
// 将网络字节序转化为主机字节序__uint16_t ntohs(__uint16_t);// 将主机字节序转化为网络字节序__uint16_t htons(__uint16_t);__uint32_t ntohl(__uint32_t);__uint32_t htonl(__uint32_t);// 若字符串有效则将字符串转换为32位二进制网络字节序的IPV4地址,否则为INADDR_NONE // 其反函数inet_ntoain_addr_t inet_addr(const char* strptr);
可以支持IPV6的IP地址转换方式
// inet_pton能够处理ipv4甚至ipv6(需要改动现在代码)if (inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr) <= 0) { perror("pton"); exit(-1);}
套接字
创建一个套接字,返回一个套接字描述符
int socket(int domain, int type, int protocol);
套接字描述符(socket file descriptor)
套接字描述符是一个整数类型的值,每个进程的进程空间里都有一个套接字描述符表,表中存放着套接字描述符和套接字数据结构的对应关系。
因此根据套接字描述符就可以找到其对应的套接字数据结构。
每个进程在自己的进程空间里都有一个套接字描述符表,但是套接字数据结构都是在操作系统的内核缓冲里
接收发送函数
ssize_t recv(int sockfd, void *buff, size_t nbytes, int flags);ssize_t send(int sockfd, const void *buff, size_t nbytes, int flags);ssize_t write (int fd,const void * buf,size_t count);ssize_t read(int fd,void * buf ,size_t count);
客户端主要函数
int connect (int sockfd,struct sockaddr * serv_addr,int addrlen);
服务器端主要函数
int bind( int sockfd , const struct sockaddr * my_addr, socklen_t addrlen);int listen(int s, int backlog);int accept(int s, struct sockaddr * addr, int * addrlen);
客户端代码
#include <iostream>#include <sys/types.h>#include <netinet/in.h>#include <sys/socket.h>#include <sys/wait.h>#include <arpa/inet.h>#include <unistd.h>const int MAX_LINE = 512;const ushort SERV_PORT = 7890;const char* SERV_IP = "127.0.0.1";int main(int argc, const char * argv[]){ int socketfd; struct sockaddr_in servaddr; memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(SERV_PORT); // 若字符串有效则将字符串转换为32位二进制网络字节序的IPV4地址// servaddr.sin_addr.s_addr = inet_addr(SERV_IP);// if (servaddr.sin_addr.s_addr == INADDR_NONE) {// perror("ip");// exit(-1);// } // 支持IPV6的新的转换方式,推荐 if (inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr) <= 0) { perror("pton"); exit(-1); } // 创建一个套接字 if ( (socketfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) { perror("socket"); exit(-1); } // 连接到主机 if (connect(socketfd, (sockaddr*)&servaddr, sizeof(servaddr)) < 0) { perror("connect"); exit(-1); } // 接收数据 char recvline[MAX_LINE+1]; long bytelen = 0; while ((bytelen = read(socketfd, recvline, MAX_LINE)) > 0) { recvline[bytelen] = 0; printf("recv --> %s\n", recvline); } close(socketfd); return 0;}
服务器代码
#include <iostream>#include <sys/types.h>#include <netinet/in.h>#include <sys/socket.h>#include <sys/wait.h>#include <arpa/inet.h>#include <unistd.h>const ushort SERV_PORT = 7890;int main(int argc, const char * argv[]){ struct sockaddr_in serveraddr; memset(&serveraddr, 0, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; serveraddr.sin_port = htons(SERV_PORT); // 系统自动获取本机IP serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); // 创建一个socket int serverfd = socket(AF_INET,SOCK_STREAM,0); if (serverfd < 0) { perror("socket"); exit(-1); } // 绑定端口 int bind_ret = bind(serverfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)); if (bind_ret < 0) { perror("bind"); exit(-1); } // 开始监听 // #2: backlog:等待连接队列的最大长度 if (listen(serverfd, 10) < 0) { perror("listen"); exit(-1); } printf("---------- listening (127.0.0.1:%d) ----------\n", SERV_PORT); // 开始轮询监听请求 bool toggle = true; while (toggle) { // 客户端信息结构 int clientfd; struct sockaddr_in clientaddr; memset(&serveraddr, 0, sizeof(serveraddr)); socklen_t len = sizeof(clientaddr); // 接收请求,建立连接 if ( (clientfd = accept(serverfd, (struct sockaddr *)&clientaddr, &len)) < 0 ) { perror("accept"); exit(-1); } // 向客户端发送信息 const char *message = "hello world"; write(clientfd, message, strlen(message)+1); // 转为点分十进制ip const char *client_ip = inet_ntoa(clientaddr.sin_addr); const ushort client_port = ntohs(clientaddr.sin_port); printf("client(%s:%u) # send -> %s\n", client_ip, client_port, message); // 关闭与客户端的连接 close(clientfd); } // 关闭服务监听 close(serverfd); return 0;}
Socket基础编程
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。