学习linux下c++服务器(第三天)

了解昨天写的linux服务器代码中用到的数据的定义

首先是大小段的定义

 tcp规定使用大端

当发送方和接受方一个使用大端一个使用小端则需要转换

在接口绑定时候使用

int getBindDone(int sock_fd)
{
//接口初始化
struct sockaddr_in serv_addr;
int ret;
memset(&serv_addr, 0, sizeof(struct sockaddr_in));
serv_addr.sin_family = AF_INET;//ipv4协议
serv_addr.sin_port = htons(SERVER_PORT);//字符串类型转数字类型
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);//ip大小端的转换
//连接嵌套字和接口
ret = bind(sock_fd, (struct sockaddr*)(&serv_addr),
sizeof(struct sockaddr_in));
assert(ret==0);
std::cout << "bind success" << std::endl;
return ret;
}

sockaddr_in 结构

接口绑定前就是对里面3个数赋值

socket返回的是文件描述符,即句柄,因为linux一切皆为文件,所以通过句柄来进行操作

参数:

 更改最大连接数,只改代码没用的,因为系统有限制,所以要改系统配置

 然后修改了一下报错方式,不使用assert使用printf加exit方式显示错误信息

新代码,加了更多的注释:

#include <stdio.h>
#include <string.h> // memset
#include <string>
#include <assert.h>
#include <sys/types.h> // AF_INET , SOCK_STREAM
#include <sys/socket.h> // socket , bind , connect , accept
#include <netinet/in.h> // sockaddr_in
#include <unistd.h>
#include <iostream>
#include<stdlib.h>
#include<errno.h>//出错处理
//定义端口号和最大连接数
#define SERVER_PORT 8099
#define LISTEN_Q_lENGTH 10
//嵌套字初始化
int getSocketDone()
{
int ret = socket(AF_INET, SOCK_STREAM, 0);
//不大于0即初始化失败
if (ret <= 0)
{
fprintf(stderr, "socket error.reason: %s\n", strerror(errno));
exit(1);
}
std::cout << "socket success" << std::endl;
return ret;

}
//接口初始化,连接嵌套字和接口
int getBindDone(int sock_fd)
{
//接口初始化
struct sockaddr_in serv_addr;
int ret;
memset(&serv_addr, 0, sizeof(struct sockaddr_in));
serv_addr.sin_family = AF_INET;//ipv4协议,ipv6位、为AF_INET6
serv_addr.sin_port = htons(SERVER_PORT);//字符串类型转整形
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);//ip大小端的转换,INADDR_ANY为0.0.0.0,监听本地所有ip
//连接嵌套字和接口
ret = bind(sock_fd, (struct sockaddr*)(&serv_addr),sizeof(struct sockaddr_in));//强制转换是因为历史原因
//不等于0即绑定失败
if (ret != 0)
{
fprintf(stderr, "Bind error.reason: %s\n", strerror(errno));
exit(1);
}
std::cout << "bind success" << std::endl;
return ret;
}
//监听接口
int getListenDone(int sock_fd)
{
int ret= listen(sock_fd, LISTEN_Q_lENGTH);
//不等于0即失败
if (ret != 0)
{
fprintf(stderr, "listen error.reason: %s\n", strerror(errno));
exit(1);
}
std::cout << "listen success" << std::endl;
return ret;
}
//获取用户标签
int getAcceptDone(int sock_fd_queue, struct sockaddr_in* client_addr,
int* client_len)
{
int sock_fd_conn;

*client_len = sizeof(struct sockaddr_in);
sock_fd_conn = accept(sock_fd_queue, (struct sockaddr*)client_addr,
(socklen_t*)client_len);//获取用户标签,如果没有用户连进来会阻塞在那

//不大于0即接收失败
if (sock_fd_conn <= 0)
{
fprintf(stderr, "Accept error.reason: %s\n", strerror(errno));
exit(1);
}
std::cout << "accept success new sockfd_conn :"+ sock_fd_conn << std::endl;
//返回用户标签
return sock_fd_conn;
}
//接收信息
int getRecvMessage(int sock_fd, char* msg, int len)
{ //sock_fd为用户标签,msg为地址,len为读取最大长度,返回值为读到的长度
int ret = recv(sock_fd, msg, len-1, 0);
msg[ret] = '\0';
//不大于0即接收失败
if (ret <= 0)
{
fprintf(stderr, "Recv error.reason: %s\n", strerror(errno));
exit(1);
}
//std::cout << "recv success receive " + ret + "bytes" << std::endl;//linux中对cout使用加法会报错
printf("recv success receive %d bytes \n", ret);
printf("recv message contents : %s\n", msg);
return ret;
}
//发送信息
int setSendMessage(int sock_fd, const char* msg, int len)
{ //sock_fd为用户标签,msg为发送信息,len为长度
int ret = send(sock_fd, msg, strlen(msg), 0);
//不大于0即发送失败
if (ret <= 0)
{
fprintf(stderr, "send error.reason: %s\n", strerror(errno));
exit(1);
}
std::cout << "send success" << std::endl;
printf("send message contents : %s\n", msg);
return ret;
}


int main(int c, char** v)
{
//套接字,服务器接口,客户端接口,接受长度
int sockfd_queue, sockfd_conn, client_len, msg_len;
struct sockaddr_in client_addr;//用户地址
char msg[1024];//存储信息

sockfd_queue = getSocketDone();//嵌套字初始化
getBindDone(sockfd_queue);//接口初始化并和嵌套字绑定
getListenDone(sockfd_queue);//开始监听访问
//不断循环接收信息
while (1)
{
sockfd_conn = getAcceptDone(sockfd_queue, &client_addr, &client_len); //获取用户接口
getRecvMessage(sockfd_conn, msg, sizeof(msg));//获取用户数据
setSendMessage(sockfd_conn, msg, sizeof(msg));//发送数据
close(sockfd_conn);//关闭用户接口
}
return 0;
}

猜你喜欢

转载自www.cnblogs.com/jnt-bob/p/12984713.html