Linux网络编程初步

目录

  • Linux网络编程初步

    • 主机字节序和网络字节序
    • 一个网络编程的例子

Linux网络编程初步

主机字节序和网络字节序

32位置机器一次性能装载4字节。那么四字节在内存的顺序影响它被累加器装载成的整数的值。主要分为大端和小端。

大端字节序是一个整数高位字节(23~31bit)存在内存的低处,低字节(0~7 bit) 存储在内存的高地址处。小端相反。

现代PC大多是小端序。小端就称为主机字节序。JVM采用大端(网络字节序)。下面是检测大端小段的案例

我的linux机子是小端序了。。。

    union {
        short value;
        char union_bytes[sizeof( short ) ];
    } test;
    test.value = 0x0102;
    printf("%d %d\n", test.union_bytes[0], test.union_bytes[1]);
    if(test.union_bytes[0] == 1 && test.union_bytes[1] == 2) {
        puts("大端序");
    } else if(test.union_bytes[0] == 2 && test.union_bytes[1] == 1) {
        puts("小端序");
    } else {
        puts("未知");
    }

linux下提供了四个函数来完成主机字节序和网络字节序的转换。

#include <netinet/in.h>
unsigned long int htonl(unsigned long int hostlong);
unsigned short int htons(unsigned short int hostshort);
unsigned long int ntohl(unsigned long int netlong);
unsigned short int ntohs(unsigned short int netshort);    

例如:host to network long => htonl

一个网络编程的例子

服务端:

#include <bits/stdc++.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <unistd.h>
#include <errno.h>

#define BUF_SIZE 1024

int main(int argc, char *argv[])
{
    if ( argc <= 2 )
    {
        printf("usage: %s ip_address port_number\n", basename( argv[0] ));
        return 1;
    }

    const char* ip = argv[1];
    int port = atoi( argv[2] );

    // ===================================================================================================================
    // 创建套接字
    //创建地址的结构体
    struct sockaddr_in address;                 // <netinet/in.h>
                                                //* Structure describing an Internet socket address.  */
                                                //    struct sockaddr_in
                                                //    {
                                                //       __SOCKADDR_COMMON (sin_);
                                                //        in_port_t sin_port;           /* Port number.  */
                                                //        struct in_addr sin_addr;      /* Internet address.  */
                                                //
                                                //        /* Pad to size of `struct sockaddr'.  */
                                                //        unsigned char sin_zero[sizeof (struct sockaddr) -
                                                //                __SOCKADDR_COMMON_SIZE -
                                                //                sizeof (in_port_t) -
                                                //                sizeof (struct in_addr)];
                                                //    };
    bzero(&address, sizeof( address ));         // <string.h> /* Set N bytes of S to 0.  */
                                                // extern void bzero (void *__s, size_t __n) __THROW __nonnull ((1));
                                                // 里面的sin_zero数组通常清零,所以这么写
    address.sin_family = AF_INET;               // AF_INET代表IPV4地址族,PF_INET是对应的协议族,宏定义的值是一样的,理论上可以混用

    inet_pton(AF_INET, ip, &address.sin_addr);  //  <arpa/inet.h>
                                                //
                                                //  extern int inet_pton (int __af, const char *__restrict __cp,
                                                //  void *__restrict __buf) __THROW;
                                                //
                                                //    /* Convert from presentation format of an Internet number in buffer
                                                //      starting at CP to the binary network format and store result for
                                                //      interface type AF in buffer starting at BUF.  */

    address.sin_port = htons( port );           // 大端字节序和小段字节序的转换 <netinet/in.h>

    int sock = socket(PF_INET, SOCK_STREAM, 0); //创建套接字    <sys/socket.h>
    assert( sock >= 0 );                        //* Create a new socket of type TYPE in domain DOMAIN, using
                                                //  protocol PROTOCOL.  If PROTOCOL is zero, one is chosen automatically.
                                                //  Returns a file descriptor for the new socket, or -1 for errors.  */
                                                //  extern int socket (int __domain, int __type, int __protocol) __THROW;
                                                //  domain: 说明系统底层的协议族,对于TCP/IP 而言,改参数设置为PF_INET(IPV4),
                                                //          PF_INET6(IPV6), UNIX本地域协议簇,改参数设置为 PF_UNIX
                                                //  type: 服务类型 SOCK_STREAM(流服务),SOCK_UGRAM(数据报)
                                                //        对于TCP,SOCK_STREAM 表示TCP,  SOCK_DGRAM 表示
                                                // protocol: 在前面的协议前提下的可选参数,一般给0就好
    // ===================================================================================================================

    // 命名socket
    int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ));
    assert( ret != -1 );                        // /* Give the socket FD the local address ADDR (which is LEN bytes long).  */
                                                //  extern int bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len)
                                                //    __THROW;
                                                //  sock就是刚刚socket的返回值。可以理解为端口和IP绑定。

    ret = listen( sock, 5 );                    // 开始监听。
    assert( ret != -1 );                        // /* Prepare to accept connections on socket FD.
                                                //  N connection requests will be queued before further requests are refused.
                                                //  Returns 0 on success, -1 for errors.  */
                                                //  extern int listen (int __fd, int __n) __THROW;
                                                //  第二个参数是处于完全连接状态(ESTABLISHED)的 socket上线。
    struct sockaddr_in client;
    socklen_t client_addrlength = sizeof( client ); // types.h  是个 unsigned int

    int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength);
                                                //    This function is a cancellation point and therefore not marked with
                                                //    __THROW.  */
                                                //    extern int accept (int __fd, __SOCKADDR_ARG __addr,
                                                //            socklen_t *__restrict __addr_len);
                                                //

    if(connfd < 0)
    {
        printf("errno is: %d\n", errno);
    }
    else
    {
        char buffer[ BUF_SIZE ];

        memset( buffer, '\0', BUF_SIZE );
        ret = recv( connfd, buffer, BUF_SIZE - 1, 0 );
        printf("[%d: %s]\n", ret, buffer);

        memset( buffer, '\0', BUF_SIZE );
        ret = recv( connfd, buffer, BUF_SIZE - 1, MSG_OOB );
        printf("[%d: %s]\n", ret, buffer);

        memset( buffer, '\0', BUF_SIZE );
        ret = recv( connfd, buffer, BUF_SIZE - 1, 0 );
        printf("[%d: %s]\n", ret, buffer);

        close( connfd );

    }
    close( sock );
    return 0;
}

客户端:

#include <bits/stdc++.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
    if(argc <= 2)
    {
        printf("usage: %s ip_address port_number\n", basename( argv[0] ));
        // basename :
        // Return the file name within directory of FILENAME.  We don't
        //  declare the function if the `basename' macro is available (defined
        //  in <libgen.h>) which makes the XPG version of this function
        //  available.
        return 1;
    }

    const char* ip = argv[1];
    int port = atoi( argv[2] );

    printf("ip = %s port = %d\n", ip, port);

    struct sockaddr_in server_address;
    bzero(&server_address, sizeof( server_address ));
    server_address.sin_family = AF_INET;    //#define PF_INET 2 //IP protocol family. // PF_INET equal AF_INET

    inet_pton( AF_INET, ip, &server_address.sin_addr );
    server_address.sin_port = htons( port );

    int sockfd = socket( PF_INET, SOCK_STREAM, 0 );
    assert( sockfd >= 0 );

    if( connect( sockfd, ( struct sockaddr* )&server_address, sizeof( server_address ) ) < 0 )
    {
        printf("connection failed\n");
    }
    else
    {
        const char *oob_data = "abc";
        const char *normal_data = "123";
        send(sockfd, normal_data, strlen(normal_data), 0);
        send(sockfd, oob_data, strlen(oob_data), MSG_OOB);
        send(sockfd, normal_data, strlen(normal_data), 0);
    }
    close(sockfd);
    return 0;
}

原文地址:https://www.cnblogs.com/Q1143316492/p/10459510.html

时间: 2024-11-07 13:21:27

Linux网络编程初步的相关文章

Linux网络编程&amp;内核学习

c语言: 基础篇 1.<写给大家看的C语言书(第2版)> 原书名: Absolute Beginner's Guide to C (2nd Edition) 原出版社: Sams 作者: (美)Greg Perry    [作译者介绍] 译者: 谢晓钢 刘艳娟 丛书名: 图灵程序设计丛书 C/C++系列 出版社:人民邮电出版社 ISBN:9787115216359上架时间:2009-12-10出版日期:2010 年1月开本:16开页码:308 说明:这本是入门最好的,最简单,最好懂 2.<

C#网络编程初步之TCP

原文:http://blog.csdn.net/mymonkey110/article/details/6841347 阅读背景:本文针对有C#的初学者而写的,主要讲解如何利用C#进行网络编程.如果你已经有一些网络编程的经验(只需要懂得网络编程的基本常识即可),并且理解C#的基本语法,那么这篇文章可以很快地带你进入C#网络编程的世界.如果你的基础不好,也不要紧,我相信这篇文章也会有你需要的内容. 网络编程基础复习: 图1. TCP编程基本模型 相信很多人看到图1应该不会陌生,这是一个利用TCP进

linux网络编程-(socket套接字编程UDP传输)

今天我们来介绍一下在linux网络环境下使用socket套接字实现两个进程下文件的上传,下载,和退出操作! 在socket套接字编程中,我们当然可以基于TCP的传输协议来进行传输,但是在文件的传输中,如果我们使用TCP传输,会造成传输速度较慢的情况,所以我们在进行文件传输的过程中,最好要使用UDP传输. 在其中,我们需要写两个程序,一个客户端,一个服务端,在一个终端中,先运行服务端,在运行客户端,在服务端和客户端都输入IP地址和端口号,注意服务端和客户端的端口号要相同,然后选择功能,在linux

Linux网络编程socket选项之SO_LINGER,SO_REUSEADDR

from http://blog.csdn.net/feiyinzilgd/article/details/5894300 Linux网络编程中,socket的选项很多.其中几个比较重要的选项有:SO_LINGER(仅仅适用于TCP,SCTP), SO_REUSEADDR. SO_LINGER 在默认情况下,当调用close关闭socke的使用,close会立即返回,但是,如果send buffer中还有数据,系统会试着先把send buffer中的数据发送出去,然后close才返回. SO_L

很全的linux网络编程技巧

注:作者王晓,本人认为总结得很好,故记之,绝无侵权之意. 1. LINUX网络编程基础知识 1 1.1. TCP/IP协议概述 1 1.2. OSI参考模型及TCP/IP参考模型 1 1.3. TCP协议 3 1.4. UDP协议 5 1.5. 协议的选择 6 2. 网络相关概念 6 2.1. socket概念 7 2.2. socket类型 8 2.3. socket信息数据结构 8 2.4. 数据存储优先顺序的转换 8 2.5. 地址格式转化 9 2.6. 名字地址转化 10 3. sock

linux网络编程 no route to host 解决方案

linux网络编程 no route to host 解决方案 [整合资料] (2013-05-13 21:38:12) 转载▼ 标签: net iptables it 分类: Linux 参考资料http://1413570.blog.51cto.com/1403570/792861http://2614223.blog.51cto.com/2604223/764757 在vmvare里面配了两台mysql,发现用mysql连不上mysql服务器,用telnet登录mysql的3306端口,发

Linux网络编程

第二章 Linux网络编程 2.1客户——服务器模型 目前大多数网络应用程序在编写时都采用客户—服务器模型,假设一端是客户,另一端是服务器,让服务器提供给客户一定的服务内容.它要求有一方(服务器方)在启动执行程序后(无限期地)等待其他客户端程序与之通信.这里可以再分为两种具体类型:并发型交互与重复型交互. (1)并发型交互.在并发型交互模式下,程序的主要运作步骤如下: ·等待一个客户请求的到来: ·生成一个新的进程或者任务来处理这个客户请求,同时这里还可以接收其他客户的请求,处理结束后,终止这个

Linux网络编程10&mdash;&mdash;使用UDP实现五子棋对战

思路 1. 通信 为了同步双方的棋盘,每当一方在棋盘上落子之后,都需要发送给对方一个msg消息,让对方知道落子位置.msg结构体如下: /* 用于发给对方的信息 */ typedef struct tag_msg { int msg_type; /* 悔棋? */ int msg_color; int msg_row; int msg_col; }MSG, *pMSG; 2. 悔棋 用链表头插法来模拟栈,链表记录了双方下子的轨迹.结构如下: /* 记录每一步的轨迹 */ typedef stru

Linux网络编程(一)

1.socket     int socket(int domain, int type,int protocol) domain:说明我们网络程序所在的主机采用的通讯协族(AF_UNIX和AF_INET等). AF_UNIX只能够用于单一的Unix系统进程间通信,而AF_INET是针对Internet的,因而可以允许在远程 主机之间通信(当我们 man socket时发现 domain可选项是 PF_*而不是AF_*,因为glibc是posix的实现 所以用PF代替了AF,不过我们都可以使用的