socket 编程
发布于: 2020 年 10 月 22 日
1 实现一个 简单的 TCP Server
服务端会相对麻烦一些代码如下:
#include <iostream>#include <netinet/in.h>#include <sys/socket.h>#include <unistd.h>#include <stdlib.h>#define PORT 8111#define MESSAGE_LEN 1024using namespace std;int main(int arc, char *argv[]) { int ret = -1; int socket_fd = -1, accept_fd = -1; int on = 1; int backlog = 10; struct sockaddr_in localaddr,remoteaddr; char in_buff[MESSAGE_LEN] = {0,}; //创建一个socket socket_fd = socket(AF_INET, SOCK_STREAM, 0); if (socket_fd == -1) { cout << "Failed to create socket!" << endl; exit(-1); } // SO_REUSEADDR 允许套接口和一个已在使用中的地址捆绑 ret = setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); if (ret == -1) { cout << "Failed to set socket options" << endl; } localaddr.sin_family = AF_INET; localaddr.sin_port = PORT; localaddr.sin_addr.s_addr = INADDR_ANY;// 绑定 ret = bind(socket_fd, (struct sockaddr *) &localaddr, sizeof(struct sockaddr)); if (ret == -1) { cout << "Failed to bind addr!" << endl; exit(-1); }// 侦听 ret = listen(socket_fd, backlog); if (ret == -1) { cout << " Failed to listen socket!" << endl; exit(-1); } for (;;) { socklen_t addr_len = sizeof(struct sockaddr); accept_fd = accept(socket_fd, (struct sockaddr *) &remoteaddr, &addr_len);// 开始接受数据 for (;;) {// 第一个空从accept_fd接受数据, ret = recv(accept_fd, (void *) in_buff, MESSAGE_LEN, 0); if (ret == 0)//没有发数据和我们断开连接了 { break; } cout << "rev:" << in_buff << endl; send(accept_fd, (void *) in_buff, MESSAGE_LEN, 0); } close(accept_fd); }// 把socket关闭 close(socket_fd); return 0;}
客户端
#include <iostream>#include <string.h>#include <stdio.h>#include <netinet/in.h>#include <arpa/inet.h>#include <sys/types.h>#include <sys/socket.h>#include <unistd.h>#define PORT 8111#define MESSAGE_LEN 1024using namespace std;int main(int arc, char *argv[]) { int ret = -1;// 创建socket连接 int socket_fd; char sendbuf[MESSAGE_LEN] = {0,};//输入的buffer char recvbuf[MESSAGE_LEN] = {0,};//输出 struct sockaddr_in serveraddr; socket_fd = socket(AF_INET,SOCK_STREAM,0); if(socket_fd<0){ cout<<"Failed to create socket!"<<endl; exit(-1); } // 连接 serveraddr.sin_family = AF_INET; serveraddr.sin_port = PORT; serveraddr.sin_addr.s_addr = inet_addr("127.0.0.1"); ret = connect(socket_fd, (struct sockaddr *)&serveraddr, sizeof(struct sockaddr)); if (ret < 0){ cout<<"Failed to connect !"<<endl; exit(-1); } // 进入连接 while (1){ memset(sendbuf,0,MESSAGE_LEN);// 从控制台中获取输入的数据,存储到sendbuf里面 gets(sendbuf); ret = send(socket_fd,sendbuf,strlen(sendbuf),0); if(ret<=0){//服务端把信息断开了,无法发送数据 cout<<"Failed to send data;"<<endl; break; } if (strcmp(sendbuf,"quit")==0){ break; }// 接受数据 ret = recv(socket_fd,recvbuf,MESSAGE_LEN,0); recvbuf[ret] = '\0'; cout<<"recv:"<<recvbuf<<endl; } close(socket_fd); return 0;}
2 高性能网络编程服务器 -fork
以fork的方式,实现高性能网络服务器
每收到一个连接就创建一个子进程,父进程就负责接收连接
重点就是在服务端做文章
#include <iostream>#include <netinet/in.h>#include <sys/socket.h>#include <unistd.h>#include <stdlib.h>#define PORT 8111#define MESSAGE_LEN 1024using namespace std;int main(int arc, char *argv[]) { int ret = -1; int socket_fd , accept_fd; int on = 1; int backlog = 10; pid_t pid; struct sockaddr_in localaddr,remoteaddr; char in_buff[MESSAGE_LEN] = {0,}; //创建一个socket socket_fd = socket(AF_INET, SOCK_STREAM, 0); if (socket_fd == -1) { cout << "Failed to create socket!" << endl; exit(-1); } // SO_REUSEADDR 允许套接口和一个已在使用中的地址捆绑 ret = setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); if (ret == -1) { cout << "Failed to set socket options" << endl; } localaddr.sin_family = AF_INET; localaddr.sin_port = PORT; localaddr.sin_addr.s_addr = INADDR_ANY;// 绑定 ret = bind(socket_fd, (struct sockaddr *) &localaddr, sizeof(struct sockaddr)); if (ret == -1) { cout << "Failed to bind addr!" << endl; exit(-1); }// 侦听 ret = listen(socket_fd, backlog); if (ret == -1) { cout << " Failed to listen socket!" << endl; exit(-1); } for (;;) { socklen_t addr_len = sizeof(struct sockaddr); accept_fd = accept(socket_fd, (struct sockaddr *) &remoteaddr, &addr_len); pid = fork(); if (pid == 0){//pid是0,说明就是子进程// 开始接受数据 for (;;) {// 第一个空从accept_fd接受数据, ret = recv(accept_fd, (void *) in_buff, MESSAGE_LEN, 0); if (ret == 0)//没有发数据和我们断开连接了 { break; } cout << "rev:" << in_buff << endl; send(accept_fd, (void *) in_buff, MESSAGE_LEN, 0); } }//如果是父进程就不会走这段代码 if (pid != 0){ close(accept_fd); } }// 把socket关闭 close(socket_fd); return 0;}
3 select实现高性能服务器
使用到异步的知识点
异步IO,以事件触发机制对IO操作进程处理。
与多线程相比,异步I/O技术系统开销小,不必维护进程和线程。
划线
评论
复制
发布于: 2020 年 10 月 22 日阅读数: 31
版权声明: 本文为 InfoQ 作者【菜鸟小sailor 🐕】的原创文章。
原文链接:【http://xie.infoq.cn/article/14e854816e462ca0bd20e3bae】。未经作者许可,禁止转载。
菜鸟小sailor 🐕
关注
一个孤独的撰写者 2020.07.30 加入
主攻云计算、云安全,c++、python、java均有涉猎
评论