基本套接字编程

                                              套接字

      所谓socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄。应用程 序通常通过"套接字"向网络发出请求或者应答网络请求。

sockaddr结构

 sockaddr_in是网络套接字地址结构,大小为16字节,定义在<netinet/in>头文件中,一般我们在程序中是使用该结构体,但是作为参数传递给套接字函数时需要强转为sockaddr类型,注意该结构体中port和addr成员是网络序的(大端结构)。

为了执行网络IO,一个进程必须做的第一件事就是调用socket函数,指定期望的通信协议类型(比如使用IPv4的TCP、使用IPv6的UDP、Unix域字节流协议)和套接字字类型(字节流、数据报或原始套接字)。

#include <sys/socket.h>
int socket(int family, int type, int protocol); // 成功返回非负描述符,出错-1

        family指定协议族;

        type指定套接字类型;

        protocol指定某个协议类型常值,或者设为0。

family的值有:

  • AF_INET IPv4协议(常用)
  • AF_INET6 Ipv6协议
  • AF_LOCAL Unix协议域
  • AF_ROUTE 路由套接字
  • AF_KEY 秘钥套接字

type的值有:

  • SOCK_STREAM 字节流套接字
  • SOCK_DGRAM 数据报套接字
  • SOCK_SEQPACKET 有序分组套接字
  • SOCK_RAW 原始套接字

protocol的值有:

  • IPPROTO_CP TCP传输协议
  • IPPROTO_UDP UDP传输协议
  • IPPROTO_SCTP SCTP传输协议

网络地址的转换

网络IP地址本是用32位表示的。为了记忆方便,可以用点分十进制数来表示IP地址。同时,网路传输与计算机内部的字符存储方式是不同的,需要用相关的函数将端口进行转换。

函数inet_addr可以将一个网络IP地址转换成为一个十进制的长整数。

long inet_addr(char *cp)

函数的参数cp是一个IP地址字符串。使用函数之前,需要在程序中加入包含下面的头文件。

#inlcude<sys/socket,h>

#icnlude<netiet/in.h>

#include<arpa/inet.h>

主机字符顺序与网络字符顺序

计算机的字符与网络字符顺序是不同的。

uint32_t (uint32_t. hostlibg)

 监听与连接

监听指的是socket的短裤处于等待状态,如果有客户端有连接请求,这个端口会接收这个连接。

连接指的是客户端 服务器端发送一个通信申请,服务器端会响应这个操作。

  listen函数

  int  listen(int s,int backlog)

 listen()声明sockfd处于监听状态, 并且最多允许有backlog个客户端处于连接等待状态, 如果接收到更多的连接请求就忽略, 这⾥里设置不会太大(一般是5).
            listen()成功返回0,失败返回-1

accept函数

int accept(int s,struct sockaddr *addr,int *addrlen);

  connect函数 

#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr* servaddr, socklen_t addrlen); // 返回:成功为0,出错-1

bind函数 

#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen); // 返回:成功为0,出错-1

 

udp服务端 

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

/*
 * UDP的网络传输服务器端程序---简单聊天服务端程序
 *  1. 创建socket           socket
 *  2. 为套接字绑定地址信息 bind
 *  3. 数据传输             recvfrom/sendto
 *  4. 关闭socket           close
 */
int main()
{
    int sockfd = -1;
    //1. 创建套接字
    sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (sockfd < 0) {
        perror("socket");
        return -1;
    }
    //2. 为套接字绑定地址信息
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(9000);
    addr.sin_addr.s_addr = inet_addr("192.168.122.131");

    socklen_t len = sizeof(struct sockaddr_in);
    int ret = bind(sockfd, (struct sockaddr*)&addr, len);
    if (ret != 0) {
        perror("bind");
        return -1;
    }
    //3. 数据传输
    while(1) {
        //1. 接收客户端数据
        struct sockaddr_in cli_addr;
        char buff[1024] = {0};
        len = 0;
        recvfrom(sockfd, buff, 1023, 0, 
                (struct sockaddr*)&cli_addr, &len);
        printf("client[%s:%d] say: %s\n", 
                inet_ntoa(cli_addr.sin_addr),
                ntohs(cli_addr.sin_port),
                buff);
        //2. 向客户端回复数据
        char tmp[1024] = {0};
        printf("you say:");
        fflush(stdout);
        scanf("%s", tmp);
        len = sizeof(struct sockaddr_in);
        sendto(sockfd, tmp, strlen(tmp), 0, 
                (struct sockaddr*)&cli_addr, len);
    }
    close(sockfd);
    return 0;
}

 udp客户端

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>

/*
 * UDP客户端程序----聊天数据的发送与接收
 *  1. 创建socket
 *  2. 收发数据
 *  3. 关闭socket
 */
int main()
{
    int sockfd = -1;

    //1. 创建socket
    sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (sockfd < 0) {
        perror("socket");
        return -1;
    }
    struct sockaddr_in serv_addr;
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(9000);//绑定端口
    serv_addr.sin_addr.s_addr = inet_addr("192.168.122.131");
    socklen_t len = sizeof(struct sockaddr_in);
    while(1) {
        char buff[1024] = {0};
        printf("you say:");
        scanf("%s", buff);
        sendto(sockfd, buff, strlen(buff), 0, 
                (struct sockaddr*)&serv_addr, len);
        //recvfrom
        char tmp[1024] = {0};
        recvfrom(sockfd, tmp, 1023, 0, 
                (struct sockaddr*)&serv_addr, &len);
        printf("serv say: %s\n", tmp);
    }
    close(sockfd);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/mashui21/article/details/81436528