socket 编程

发布于: 2020 年 10 月 22 日
socket编程

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 1024
using 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 1024
using 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 1024
using 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 日 阅读数: 17
用户头像

一个孤独的撰写者 2020.07.30 加入

主攻云计算、云安全,c++、python、java均有涉猎

评论

发布
暂无评论
socket编程