• 基于Socket编程下 实现Linux-Linux、Linux-Windows tcp通信



    前言

    阅读本篇前 请先具备socket编程与TCP协议相关基础,可移步
    “ Socket编程基础 ”“ TCP传输控制协议 ”进行知识充能。

    一、Linux - Linux

    服务器 server

    ① 调用 socket()函数打开套接字,得到套接字描述符;

    //创建一个socket文件,也就是打开一个网络通讯端口,类型是IPV4(AF_INET)+TCP(SOCK_STREAM)
    	int serv_sock = socket(AF_INET, SOCK_STREAM,0);
    
    • 1
    • 2

    ② 调用 bind()函数将套接字与 IP 地址、端口号进行绑定;

    	struct sockaddr_in serv_addr;//ipv4,使用结构体地址类型sockaddr_in
    	memset(&serv_addr, 0, sizeof(serv_addr));//先清空初始值
    	serv_addr.sin_family = AF_INET;
    	serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");//本机ip环回地址,这里还可以使用inet_pton函数进行地址转换
    	serv_addr.sin_port = htons(8899);//可自定义一个端口8899(一选择大于5000)
        bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));  //绑定
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    ③ 调用 listen()函数让服务器进程进入监听状态;

    listen(serv_sock,3); //设置最大连接数为3
    
    • 1

    ④ 调用 accept()函数获取客户端的连接请求并建立连接;

    int clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);
    
    • 1

    ⑤ 调用 read、write 与客户端进行通信;

    read(clnt_sock,recv_buf,sizeof(recv_buf)-1);
    write(clnt_sock,tmp,sizeof(tmp));   
    
    • 1
    • 2

    ⑥ 调用 close()关闭套接字。

    close(clnt_sock);
    close(serv_sock); 
    
    • 1
    • 2

    客户端 client

    ① 调用 socket()函数打开套接字,得到套接字描述符;

    //创建socket,用于和服务端通信
        int sock = socket(AF_INET, SOCK_STREAM, 0);
    
    • 1
    • 2

    ② 指定服务器ip与端口;

    	struct sockaddr_in serv_addr;
        memset(&serv_addr, 0, sizeof(serv_addr));
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_addr.s_addr = inet_addr("192.168.1.181");//注意,这里是服务端的ip和端口
        serv_addr.sin_port = htons(8899);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    ③ 调用 connect 连接远端服务器;

    connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr))
    
    • 1

    ④ 调用 read、write 与服务器进行通信;

    read(sock,recv_buf,sizeof(recv_buf)-1);
    write(sock,send_buf,sizeof(send_buf));
    
    • 1
    • 2

    ⑤ 调用 close()关闭套接字。

    close(sock);   //断开连接
    
    • 1

    通信实操

    1. 进入Linux平台下编译好的文件夹中,同时打开俩个终端,对已敲好的服务器、客户端程序分别进行编译、运行
      在这里插入图片描述
      先运行服务器端的程序,然后再运行客户端,可以看出,上面服务器与客户端连接成功,接下来试试传输数据吧
      在这里插入图片描述
      可见,通信成功!

    二、socket编程在windows和linux下的区别

    • 1. 头文件
    // Linux头文件主要包含
      #include <sys/socket.h>
      #include <netinet/in.h>
      #include <netdb.h>
      #include <arpa/inet.h>
      
    // windows下则是包含
      #include <Winsock2.h>
      #pragma comment(lib,“Ws2_32.lib”)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 2. 初始化

    windows下需要用WSAStartup();linux下不需要
    对应的退出清理用WSACleanup( );linux下不需要

    	WSADATA s; // 用来储存调用AfxSocketInit全局函数返回的Windows Sockets初始化信息  
    	if (WSAStartup(MAKEWORD(2, 2), &s) != 0) // 通过连接两个给定的无符号参数,首个参数为低字节,使用2.2版本的Socket
            {
                printf("Init Windows Socket Failed! Error: %d\n", GetLastError());
                getchar();
                return -1;
            }
            
    	WSACleanup( );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 3. socket套接字类型

    Linux中socket为整形,
    Windows中为一个SOCKET类型。

    int sock = socket(AF_INET, SOCK_STREAM, 0);
    SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
    
    • 1
    • 2
    • 4. 收发数据
      Linux中使用read和write
      windows中使用recv和send
    send(sock,send_buf,sizeof(send_buf),0);
    recv(sock,recv_buf,sizeof(recv_buf)-1,0);
    
    • 1
    • 2
    • 5. 获取错误码
      windows下WSAGetLastError() ;
      linux下设置errno变量 用geterror()取得错误码;
    printf("Init Windows Socket Failed! Error: %d\n", GetLastError());
    printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);
    
    • 1
    • 2
    • 6. 设置socket属性
      Linux下为 fcntl (fd, F_SETFL, flag | O_NONBLOCK);
      Windows下为 ioctlsocket (fd, FIONBIO, (unsigned long *) &flag);

    • 7. 毫秒级时间获取
      windows下 GetTickCount()
      linux下 gettimeofday()

    • 8. WSA宏
      windows下WSA相关的操作
      linux下WSA相关的操作在Linux不必要,直接去掉即可

    • 9. 多线程

     //(windows) ------------ (linux)
      process.h   ---->  pthread.h
     _beginthread ---->  pthread_create
     _endthread   ---->  pthread_exit
    
    • 1
    • 2
    • 3
    • 4

    三、Windows - Linux

    该部分可根据 Linux-Linux 下的程序进行修改,其通信原理一毛一样,所以这个就留给读者做课后作业吧。

    四、程序源码

    若需程序源码可留言评论区或直接私信 即可。

  • 相关阅读:
    MySQL日志及执行计划
    javaEE -6(10000详解文件操作)
    基于SSM的共享客栈管理系统的设计与实现
    k8s核心概念Controller进阶之DaemonSet、Job、CronJob
    基于PCA主成分分析的BP神经网络回归预测研究(Matlab代码实现)
    分享117个PHP源码,总有一款适合你
    品达通用_9. pd-tools-log
    CompletableFuture学习总结
    HTML网页设计【足球科普】学生DW静态网页设计
    HTML入门(详细)
  • 原文地址:https://blog.csdn.net/Dustinthewine/article/details/127630910