Colderleo's blog Colderleo's blog
首页
Linux
C++
Python
前端
工具软件
mysql
索引
关于
GitHub (opens new window)

Colder Leo

热爱代码的打工人
首页
Linux
C++
Python
前端
工具软件
mysql
索引
关于
GitHub (opens new window)
  • bug定位的一些情形
  • c++性能调优,可能的情况
  • total-编程知识点集锦
  • hpc_common.hpp
  • memory order 内存模型
  • 类型推导之auto-template-decltype
  • 完美转发forward源码分析
  • 左值和右值,右值引用、重载 std-move,引用折叠
  • cmake用法
  • alignas、alignof、sizeof实现内存对齐分配
  • 通过宏定义控制debug打印
  • 程序耗时性能测试
  • 线程池开源项目阅读
  • C++类中包含没有默认构造函数的成员
  • C++可变参数模板
  • C++属性继承 public protected private
  • C++智能指针
  • C++导出so的方法,以及extern C 注意事项
  • 四种spin lock
  • condition_variable和unique_lock
  • dpdk、kernel bypass
  • 智能网卡solarflare、Mellanox、X10等
  • 汇编寄存器和常见指令
  • c++ 类的静态成员变量未定义
  • C++获取类成员函数地址
  • preload示例
  • C++异常安全和RAII
  • C++11单例模式
  • C++歪门邪道
  • boost-program-option用法
  • c++17通过模板获取类成员的个数
  • 通过模板实现结构体成员拷贝-按成员名匹配
  • STL学习路径
  • boost库安装使用方法
  • C++文件读写
  • linux下socket通信demo,server和client
  • makefile写法
  • RxCpp
  • C++
gaoliu
2021-10-06

linux下socket通信demo,server和client

C语言中文网的socket教程,一系列,非常棒,不过有些章节要收费。 http://c.biancheng.net/socket/

一篇博客,单个的socket client和server的通信,代码很好,我修改了一小部分,并加上了注释,如下。 https://www.cnblogs.com/zkfopen/p/9441264.html

# server.cpp

//server.cpp

#include<stdlib.h>  //这5个是unix常用库,加了不会错,不加很可能会出错。
#include<unistd.h>
#include<string.h>  //memset() 等
#include<stdio.h>   //printf
#include<errno.h>

#include<sys/types.h>
#include<sys/socket.h>  //socekt通信,这3个都要
#include<netinet/in.h>  //定义了sockaddr_in 
#include<arpa/inet.h>  //包含inet_addr("127.0.0.1")

#define MAXSIZE 4096

int main(int argc, char** argv){
    
    //AF_INET,表示ipv4,还有AF_INET6; AF意思是Address Family
    //SOCK_STREAM表示TCP,还有 SOCK_DGRAM:UDP   
    //socket函数第三个参数,0,表示传输协议。它有三种取值,IPPROTO_TCP,IPPROTO_UDP,0。 0表示根据第二个参数自动推演,所以一般就用0
    int  server_sock;
    if( (server_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){
        printf("create socket error: %s\n", strerror(errno));
        return 0;
    }

    struct sockaddr_in  addr;
    memset(&addr, 0, sizeof(addr));//把addr的内存初始化为0。这句相当于是快速的初始化。
    addr.sin_family = AF_INET;//ipv4
    // addr.sin_addr.s_addr = htonl(INADDR_ANY);// 0.0.0.0, 监听所有网卡的所有ip地址。 htonl host to network long,把host字节序转换为网路字节序,long
    addr.sin_addr.s_addr = inet_addr("0.0.0.0");// 0.0.0.0, 监听所有网卡的所有ip地址。
    addr.sin_port = htons(6666);//host to network short.

    // bind 绑定成功,返回0,失败返回-1
    int bind_ret = bind(server_sock, (struct sockaddr*)&addr, sizeof(addr));
    if(-1 == bind_ret){//addr类型是sockaddr_in,这里要给它转成sockaddr
        printf("bind socket error: %s\n", strerror(errno));
        return 0;
    }

    int listen_ret = listen(server_sock, 10);
    if(-1 == listen_ret){//10是请求队列的长度。并发量小可以设置成10或20。
        printf("listen socket error: %s\n", strerror(errno));
        return 0;
    }

    printf("======waiting for client's request======\n");
    int client_sock, n;
    char  buff[4096];
    while(1){
        //接受客户端socket连接
        struct sockaddr_in client_addr;
        socklen_t len = sizeof(client_addr);
        client_sock = accept(server_sock, (struct sockaddr*)&client_addr, &len);
        //如果不关心客户端的地址,也可以这样:accept(server_sock, NULL, NULL); 
        if( -1 == client_sock){
            printf("accept socket error");
            continue;
        }
        
        //接收数据
        n = recv(client_sock, buff, MAXSIZE-1, 0);//MAXSIZE是接收数据的长度,第4个参数一般配置为0
        buff[n] = '\0';
        printf("recv msg from client: %s\n", buff);
        close(client_sock);
    }
    close(server_sock);
    return 0;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

# client.cpp

//client.cpp

#include<stdio.h>  //这4个是unix下的常用库
#include<stdlib.h>
#include<string.h>
#include<unistd.h>

#include<errno.h>
#include<sys/socket.h>  
#include<netinet/in.h>
#include<arpa/inet.h>   //包含inet_addr("127.0.0.1")

#define MAXSIZE 4096

int main(int argc, char** argv){
    char  recvline[4096], sendline[4096];

    //运行时输入ip地址作为参数,
    // if( argc != 2){
    //     printf("usage: ./client <ipaddress>\n");
    //     return 0;
    // }

    int sock_client = socket(AF_INET, SOCK_STREAM, 0);
    if( sock_client < 0){
        printf("create socket error: %s\n", strerror(errno));
        return 0;
    }

    struct sockaddr_in  addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(6666);
    //addr.sin_addr.s_addr = inet_addr(argv[1]);//将main传入的参数赋给addr.sin_addr
    addr.sin_addr.s_addr = inet_addr("127.0.0.1");//将main传入的参数赋给addr.sin_addr
    
    //也可以用下面的方法传,这个方法的好处是能检测输入是否正确,另外inet_pton这个函数ipv6也可以处理。
    // if( inet_pton(AF_INET, argv[1], &addr.sin_addr) <= 0){
    //     // inet_pton 将点分十进制串转换成网络字节序二进制值,此函数对IPv4地址和IPv6地址都能处理。
    //     printf("inet_pton error for %s\n",argv[1]);
    //     return 0;
    // }

    int connect_ret = connect(sock_client, (struct sockaddr*)&addr, sizeof(addr));
    if(connect_ret < 0){
        printf("connect error: %s(errno: %d)\n",strerror(errno),errno);
        return 0;
    }

    printf("send msg to server: \n");
    fgets(sendline, 4096, stdin);
    if(send(sock_client, sendline, strlen(sendline), 0) < 0){
        printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);
        return 0;
    }
    // close(sock_client);
    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

# struct sockaddr和struct sockaddr_in的区别和用法

https://blog.csdn.net/slvher/article/details/8856003


//sockaddr_in的结构
struct sockaddr_in { 
    short int sin_family;
    unsigned short int sin_port; 
    struct in_addr sin_addr;                
    unsigned char sin_zero[8];
}   


1
2
3
4
5
6
7
8
9
10
编辑 (opens new window)
上次更新: 2023/05/07, 17:27:54
C++文件读写
makefile写法

← C++文件读写 makefile写法→

最近更新
01
通过模板实现结构体成员拷贝-按成员名匹配
05-07
02
c++17通过模板获取类成员的个数
05-01
03
avx-sse切换惩罚
04-30
更多文章>
Theme by Vdoing | Copyright © 2019-2023 Colder Leo | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×