TCP/IP网络编程_hello,world!

复制代码
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/socket.h>
//错误处理宏
#define error_handling(message){std::cerr<<message<<"error!"<< strerror(errno) <<std::endl;\
    exit(1);}
int main(int argc,char*argv[]){
    int serv_sock,clnt_sock;
    //零构造地址信息
    struct sockaddr_in serv_addr{};
    struct sockaddr_in clnt_addr{};
    socklen_t clnt_addr_size;//地址信息大小
    std::string message="hello,world!";//要传输的数据
    //错误输入处理
    if(argc!=2){
        std::cout<<"Usage:"<<argv[0]<<"<port>"<<std::endl;
        exit(1);
    }
    //创建TCP套接字
    serv_sock=socket(PF_INET,SOCK_STREAM,0);
    if(serv_sock==-1)error_handling("socket");
    //设置地址信息
    serv_addr.sin_family=PF_INET;
    //INADDR_ANY宏定义为 0(uint32_t),表示"任意 IP 地址"(0.0.0.0)。用于服务器绑定时,监听所有网络接口
    serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);//将主机字节序的 32 位无符号长整数(uint32_t)转换为网络字节序
    serv_addr.sin_port=htons(atoi(argv[1])/*将字符串转换为整数*/);
    //绑定地址信息
    if(bind(serv_sock,(const sockaddr*)&serv_addr,sizeof(serv_addr))==-1)error_handling("bind");
    //监听客户端
    if(listen(serv_sock,5)==-1)error_handling("listen");
    clnt_addr_size=sizeof(clnt_addr);
    //建立连接并生成客户端套接字
    clnt_sock=accept(serv_sock,(sockaddr*)&clnt_addr,&clnt_addr_size);
    if(clnt_sock==-1)error_handling("accept");
    //写入数据
    write(clnt_sock,(void*)message.c_str(),message.size());
    //断开连接
    close(clnt_sock);
    //关闭服务器端套接字
    close(serv_sock);
    return 0;
}

#include<iostream>
#include<cstdlib>
#include<cstring>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/socket.h>
//错误处理宏
#define error_handling(message){std::cerr<<message<<"error!"<< strerror(errno) <<std::endl;\
    exit(1);}
int main(int argc,char*argv[]){
    //创建文件描述符
    int sock;
    //零构造地址信息
    struct sockaddr_in serv_addr{};
    //缓冲区
    std::string message;
    int str_len;//记录接收到的字节数
    //错误输入处理
    if(argc!=3){
        std::cout<<"Usage:"<<argv[0]<<"<IP><port>"<<std::endl;
        exit(1);
    }
    //创建TCP套接字
    sock=socket(PF_INET,SOCK_STREAM,0);
    if(sock==-1)error_handling("socket");
    //设置地址信息
    serv_addr.sin_addr.s_addr=inet_addr(argv[1]);//将点分十进制 IP 字符串(如 "127.0.0.1")转换为网络字节序的 32 位整数(in_addr_t,通常 uint32_t)
    serv_addr.sin_family=PF_INET;
    serv_addr.sin_port=htons(atoi(argv[2]));//将主机字节序的 16 位无符号短整数(uint16_t)转换为网络字节序(大端序)
    //连接套接字
    if(connect(sock,(const sockaddr*)&serv_addr,sizeof(serv_addr))==-1)error_handling("connect");
    //读取信息
    message.resize(30); // 调整大小
    //读取数据 read读取时会阻塞当前线程 属于同步阻塞的IO函数
    str_len=read(sock,&message[0],message.size());
    if(str_len==-1)error_handling("read");
    message.resize(str_len);// 截断到实际长度,避免打印垃圾
    //打印信息
    std::cout<<"message from server:"<<message<<std::endl;
    close(sock);//关闭套接字
    return 0;
}

这是一个简单的单连接 TCP echo 示例(服务器发送固定消息,客户端接收打印)。流程基于标准 socket API:

  1. 服务器端启动
    • 创建监听套接字 (serv_sock = socket(PF_INET, SOCK_STREAM, 0))。
    • 设置地址:family=PF_INET, addr=htonl(INADDR_ANY)(任意 IP), port=htons(atoi(argv[1]))(指定端口)。
    • bind() 绑定地址,listen() 进入监听(队列大小 5)。
    • accept() 阻塞等待客户端连接,生成 clnt_sock(已连接套接字)。
    • 通过 clnt_sock write() 发送消息 ("hello,world!")。
    • close(clnt_sock)close(serv_sock) 断开。
  1. 客户端启动(在服务器监听后):
    • 创建套接字 (sock = socket(PF_INET, SOCK_STREAM, 0))。
    • 设置服务器地址:family=PF_INET, addr=inet_addr(argv[1]), port=htons(atoi(argv[2]))
    • connect() 发起连接(三次握手)。
    • read() 阻塞读取数据到缓冲 (message),打印。
    • close(sock) 断开(四次挥手)。
  1. 底层机制
    • TCP 确保可靠传输(重传、顺序)。
    • 字节序转换 (htons/htonl) 标准化为大端序。
    • 数据从应用层 → TCP 层 → IP 层 → 网卡传输。

注:网络字节序是大端序,也就是高地址在高位,低地址在低位(高位在前低位在后)小端序与其相反,有些系统可能采用小端序,为在网络上统一,网络字节序统一使用大端序

相关推荐
Elias不吃糖1 天前
Java Lambda 表达式
java·开发语言·学习
guygg881 天前
一级倒立摆MATLAB仿真程序
开发语言·matlab
暮色_年华1 天前
随想 2:对比 linux内核侵入式链表和 STL 非侵入链表
linux·c++·链表
情缘晓梦.1 天前
C语言指针进阶
java·开发语言·算法
世转神风-1 天前
qt-字符串版本与数值版本互转
开发语言·qt
极客代码1 天前
深入解析C语言中的函数指针:原理、规则与实践
c语言·开发语言·指针·状态机·函数·函数指针
w-w0w-w1 天前
C++模板参数与特化全解析
开发语言·c++
不绝1911 天前
C#核心:继承
开发语言·c#
大锦终1 天前
递归回溯综合练习
c++·算法·深度优先