地址结构sockaddr_in

其中包含:IP地址端口号协议族
推荐使用sockaddr_in,而不建议使用sockaddr
sockaddr_insockaddr是等价的,但sockaddr_in字段更清晰

/*
 * Socket address, internet style.
 */
struct sockaddr_in {
    __uint8_t   sin_len;
    sa_family_t sin_family;
    in_port_t   sin_port;
    struct      in_addr sin_addr;
    ];
};

sockaddr_in字段描述

// 地址家族,通常使用AF_INET代表TCP/CP协议族(AF_INET6代表IPV6)
sockaddr_in.sin_family

// 端口号,必须转化为网络字节序使用htons和ntohs
sockaddr_in.sin_port

// 用于存储ip地址,必须是网络字节序
sockaddr_in.sin_addr

// 为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节
sockaddr_in.sin_zero

sockaddr_in字段初始化

struct sockaddr_in servaddr;
bzero(&servaddr, sizeof(servaddr));

servaddr.sin_family = AF_INET;
servaddr.sin_port = htons();

// 若字符串有效则将字符串转换为32位二进制网络字节序的IPV4地址
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
// 检测转化IP是否出错
if (servaddr.sin_addr.s_addr == INADDR_NONE) {
    perror("ip");
    exit(-);
}

可以支持IPV6的IP地址转换方式

// inet_pton能够处理ipv4甚至ipv6(需要改动现在代码)
) {
    perror("pton");
    exit(-);
} 

网络字节序和IP转换函数

// 将网络字节序转化为主机字节序
__uint16_t ntohs(__uint16_t);
// 将主机字节序转化为网络字节序
__uint16_t htons(__uint16_t);

__uint32_t ntohl(__uint32_t);
__uint32_t htonl(__uint32_t);
// 若字符串有效则将字符串转换为32位二进制网络字节序的IPV4地址,否则为INADDR_NONE
// 其反函数inet_ntoa
in_addr_t inet_addr(const char* strptr);

网络字节顺序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释,网络字节顺序采用big-endian排序方式。

序号
英文名
中文名
描述
1
big-endian
大尾顺序
地址的低位存储值的高位
2
little-endian
小尾顺序
地址的低位存储值的低位 

想判断你的设备大小端吗?使用C语言的Union就可以判断!请看这里

套接字

创建一个套接字,返回一个套接字描述符

int socket(int domain, int type, int protocol);

套接字描述符(socket file descriptor)
套接字描述符是一个整数类型的值,每个进程的进程空间里都有一个套接字描述符表,表中存放着套接字描述符和套接字数据结构的对应关系。
因此根据套接字描述符就可以找到其对应的套接字数据结构。
每个进程在自己的进程空间里都有一个套接字描述符表,但是套接字数据结构都是在操作系统的内核缓冲里

接收发送函数

ssize_t recv(int sockfd, void *buff, size_t nbytes, int flags);
ssize_t send(int sockfd, const void *buff, size_t nbytes, int flags);

ssize_t write (int fd,const void * buf,size_t count);
ssize_t read(int fd,void * buf ,size_t count);

客户端主要函数

int connect (int sockfd,struct sockaddr * serv_addr,int addrlen);

服务器端主要函数

int bind( int sockfd , const struct sockaddr * my_addr, socklen_t addrlen);
int listen(int s, int backlog);
int accept(int s, struct sockaddr * addr, int * addrlen);

客户端代码

#include <iostream>

#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <unistd.h>

;
;
const char*     SERV_IP     = "127.0.0.1";

int main(int argc, const char * argv[])
{
    int socketfd;

    struct sockaddr_in servaddr;
    memset(&servaddr, , sizeof(servaddr));

    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(SERV_PORT);

    // 若字符串有效则将字符串转换为32位二进制网络字节序的IPV4地址
//    servaddr.sin_addr.s_addr = inet_addr(SERV_IP);
//    if (servaddr.sin_addr.s_addr == INADDR_NONE) {
//        perror("ip");
//        exit(-1);
//    }

    // 支持IPV6的新的转换方式,推荐
    ) {
        perror("pton");
        exit(-);
    }

    // 创建一个套接字
    )) <  ) {
        perror("socket");
        exit(-);
    }

    // 连接到主机
    ) {
        perror("connect");
        exit(-);
    }

    // 接收数据
    ];
    ;
    ) {
        recvline[bytelen] = ;
        printf("recv --> %s\n", recvline);
    }

    close(socketfd);
    ;
}

服务器代码

#include <iostream>

#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <unistd.h>

;

int main(int argc, const char * argv[])
{
    struct sockaddr_in serveraddr;
    memset(&serveraddr, , sizeof(serveraddr));

    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(SERV_PORT);
    // 系统自动获取本机IP
    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);

    // 创建一个socket
    );
    ) {
        perror("socket");
        exit(-);
    }

    // 绑定端口
    int bind_ret = bind(serverfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
    ) {
        perror("bind");
        exit(-);
    }

    // 开始监听
    // #2: backlog:等待连接队列的最大长度
    ) < ) {
        perror("listen");
        exit(-);
    }

    printf("---------- listening (127.0.0.1:%d) ----------\n", SERV_PORT);

    // 开始轮询监听请求
    bool toggle = true;
    while (toggle) {
        // 客户端信息结构
        int clientfd;
        struct sockaddr_in clientaddr;
        memset(&serveraddr, , sizeof(serveraddr));
        socklen_t len = sizeof(clientaddr);

        // 接收请求,建立连接
         ) {
            perror("accept");
            exit(-);
        }

        // 向客户端发送信息
        const char *message = "hello world";
        write(clientfd, message, strlen(message)+);

        // 转为点分十进制ip
        const char *client_ip = inet_ntoa(clientaddr.sin_addr);
        const ushort client_port = ntohs(clientaddr.sin_port);
        printf("client(%s:%u) # send -> %s\n", client_ip, client_port, message);

        // 关闭与客户端的连接
        close(clientfd);
    }

    // 关闭服务监听
    close(serverfd);
    ;
}

Socket基础编程的更多相关文章

  1. 【Socket】Java Socket基础编程

    Socket是Java网络编程的基础,了解还是有好处的, 这篇文章主要讲解Socket的基础编程.Socket用在哪呢,主要用在进程间,网络间通信.本篇比较长,特别做了个目录: 一.Socket通信基 ...

  2. C#网络程序设计(2)Socket基础编程

        本节介绍如何使用基础Socket实现TCP通信.     (1)Socket详细介绍: Socket的英文原义是"孔"或"插座".通常称作"套 ...

  3. TCP(Socket基础编程)

    1.TCP特点: 面向连接.可靠安全.传输量大.速度较慢 2.socket编程主要依靠两个类:socket .serversocket example1:客户端可以不停输入字符串,服务端返回字符串的大 ...

  4. socket基础编程-1

    server端和client端 1.server端: import socket server=socket.socket() server.bind(('localhost',8080)) serv ...

  5. socket基础编程-2

    client端: import socket while True: client=socket.socket(socket.ANET,socket.SOCK_STREAM) client.conne ...

  6. C++ SOCKET 基础编程

    { http://c.biancheng.net/socket/ }

  7. Linux应用程序设计之网络基础编程

    1.TCP/IP协议概述 1.1.OSI参考模型及TCP/IP参考模型 OSI协议参考模型是基于国际标准化组织(ISO)的建议发展起来的,从上到下工分为7层:应用层,表示层,会话层,传输层,网络层,数 ...

  8. Python基础笔记系列十三:socket网络编程

    本系列教程供个人学习笔记使用,如果您要浏览可能需要其它编程语言基础(如C语言),why?因为我写得烂啊,只有我自己看得懂!!使用python编写一个简易的服务端程序和客户端程序,启动服务端和客户端(监 ...

  9. Java Web 基础(一) 基于TCP的Socket网络编程

    一.Socket简单介绍 Socket通信作为Java网络通讯的基础内容,集中了异常.I/O流模式等众多知识点.学习Socket通信,既能够了解真正的网络通讯原理,也能够增强对I/O流模式的理解. 1 ...

随机推荐

  1. TWaver初学实战——基于HTML5的交互式地铁图

    每天坐地铁,经常看地铁图,有一天突然想到,地铁图不也是一种拓扑结果吗?TWaver到底能与地铁图擦出怎样的火花呢?   想到就干,先到网上找幅参考图.各种风格的地铁图还挺多,甚至有大学生自主设计制作, ...

  2. 设置 Eclipse 智能代码提示,大幅度减少 alt+/ 使用频率,打每个字都出现代码提示的办法

    以前网上有个英文版本的,现在自己汉化一下...O(∩_∩)O 哈哈 ~   http://www.cnblogs.com/lidabo/archive/2013/03/05/2944245.html ...

  3. 华为HG8240光猫-破解-联通-2016-telnet-http

    序 我与大家想法基本一致,拿到联通的光猫后,心想它应该是个路由器吧,如果让它自己拨号上网就好了,即省一台路由器,又省电了.抱着这个想法,在2013年里,我搜罗了不少文章,经过Q群,搜索,询问,阅读,理 ...

  4. GBDT(MART)

    转自:http://blog.csdn.net/w28971023/article/details/8240756 在网上看到一篇对从代码层面理解gbdt比较好的文章,转载记录一下: GBDT(Gra ...

  5. Matlab梯度下降解决评分矩阵分解

    for iter = 1:num_iters %梯度下降 用户向量 for i = 1:m %返回有0有1 是逻辑值 ratedIndex1 = R_training(i,:)~=0 ; %U(i,: ...

  6. Oracle NULL 和空值

      如果你工作中用到了Oracle,你必须要留意NULL和空值的处理与SQL Server上的不同.现在让我们看些例子. 建立这张数据库表并插入记录 CREATE TABLE TestNull(Col ...

  7. ibatis的iterate使用

    Iterate:这属性遍历整个集合,并为 List 集合中的元素重复元素体的内容. Iterate 的属性:       prepend  - 可被覆盖的 SQL 语句组成部分,添加在语句的前面(可选 ...

  8. Sqli-labs less 18

    Less-18 本关我们这里从源代码直接了解到 对uname和passwd进行了check_input()函数的处理,所以我们在输入uname和passwd上进行注入是不行的,但是在代码中,我们看到了 ...

  9. this的使用、继承、super

    1.this的使用 1)可以用于区分局部变量 Person(int age,string name) { this.age=age; this.name=name; } 2)构造方法中,用this调用 ...

  10. Linux关于watch的用法

    Linux关于watch的用法 2011-07-20      0个评论       收藏    我要投稿 watch 是一个非常实用的命令,基本所有的 Linux 发行版都带有这个小工具,如同名字一 ...