C语言 系统函数与库函数的区别、网络编程(UDP)

系统函数与库函数的区别:

系统函数可以说是原材料,库函数是对原函数的封装。

==================================================================

网络编程(UDP)

==================================================================

1.创建套接字:

函数原型:

int socket(int domain , int tpye , int potocol);

头文件:
#include <sys/types.h>
#include <sys/socket.h>

参数分析:

  • domain ----> 定使用何种的地址类型, 完整的定义在/usr/include/bits/socket.h内, 底下是常见的协议:
   PF_UNIX/PF_LOCAL/AF_UNIX/AF_LOCAL UNIX 进程通信协议
   PF_INET/AF_INET Ipv4 网络协议
   PF_INET6/AF_INET6 Ipv6 网络协议
   PF_IPX/AF_IPX IPX-Novell 协议
   PF_NETLINK/AF_NETLINK 核心用户接口装置
   PF_X25/AF_X25 ITU-T X. 25/ISO-8208 协议
   PF_AX25/AF_AX25 业余无线 AX. 25 协议
   PF_ATMPVC/AF_ATMPVC 存取原始 ATM PVCs
   PF_APPLETALK/AF_APPLETALK appletalk (DDP)协议
   PF_PACKET/AF_PACKET 初级封包接口
  • type --> 有下列几种数值:
SOCK_STREAM //提供双向连续且可信赖的数据流, 即 TCP. 支持 OOB 机制, 在所有数据传送前必须使用 connect()来建立连线状态.
SOCK_DGRAM 使用不连续不可信赖的数据包连接 说的就是UDP
    SOCK_SEQPACKET 提供连续可信赖的数据包连接
    SOCK_RAW 提供原始网络协议存取
    SOCK_RDM 提供可信赖的数据包连接
    SOCK_PACKET 提供和网络驱动程序直接通信
    
    
  • protocol --> 用来指定 socket 所使用的传输协议编号, 通常此参考不用管它, 设为 0 即可.

反回值:

  • 成功则返回 socket 处理代码(待链接的套接字)
    失败返回-1.

==================================================================

2. 配置地址信息:
struct sockaddr_in
{
	 u_short sin_family; // 地址族
	 u_short sin_port; // 端口
	 struct in_addr sin_addr; // IPV4 地址
	 char sin_zero[8];
};
struct in_addr
{
 	in_addr_t s_addr; // 无符号 32 位网络地址
};

配置端口号

htons ( 将 16 位主机字符顺序转换成网络字符顺序 )

头文件:
#include <netinet/in.h>

定义函数:

unsigned short int htons(unsigned short int hostshort);

参数分析:

  • hostshort ----> 需要转换的16位主机序整数

返回值:

  • 返回对应的网络字符顺序
配置IPV4地址:

(1) inet_addr ( 将网络地址转成二进制的数字 )

头文件:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

定义函数:

unsigned long int inet_addr(const char *cp);

参数分析:

  • cp ----> 网络地址字符串转换成网络所使用的二进制数字(需要转换的点分十进制网路地址)

返回值:

  • 成功则返回对应的网络二进制的数字
    失败返回-1.

(2) inet_ntoa ( 将网络二进制的数字转换成网络地址 )

头文件:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

定义函数:

  char * inet_ntoa(struct in_addr in);

参数分析:

  • in ----> 需要转换的二进制网路地址

返回值:

  • 成功则返回字符串指针
    失败则返回 NULL.

================================================================

3.绑定地址信息(服务器端):

bind ( 对 socket 定位 )

头文件:
#include <sys/types.h>
#include <sys/socket.h>

定义函数:

  int bind(int sockfd, struct sockaddr * my_addr, int addrlen);

参数分析:

sockfd --> socket 处理代码 (socket的返回值待链接的套接字)
  my_addr --> 包含本地地址(IP+PORT)的通用地址结构体的指针(sockaddr_in结构体)
  addrlen --> 结构体长度

返回值:

  • 成功:0
    失败:-1

================================================================

4.等待来信(服务器端):

recvfrom ( 经 socket 接收数据 )

头文件:
#include <sys/types.h>
#include <sys/socket.h>

定义函数:

int recvfrom(int s, void *buf, int len, unsigned int flags, struct sockaddr *from,int *fromlen);

参数分析:

s --> 接收的socket套接字
  buf --> 接收到的信息存放到哪里
  len --> 接收信息的长度
  • flags --> flags 一般设 0. 其他数值定义如下:
MSG_OOB 接收以 out-of-band 送出的数据.
MSG_PEEK 返回来的数据并不会在系统内删除, 如果再调用 recv()会返回相同的数据内容.
MSG_WAITALL 强迫接收到 len 大小的数据后才能返回, 除非有错误或信号产生.
MSG_NOSIGNAL 此操作不愿被 SIGPIPE 信号中断返回值成功则返回接收到的字符数, 失败返回-1,
from --> 信息来源哪里
fromlen --> 地址结构体的长度


返回值:

  • 成功则返回接收到的字符数
    失败则返回-1, 错误原因存于 errno 中.

=====================================================================

5.发送信息(客户端):

sendto ( 经 socket 传送数据 )

头文件:
#include <sys/types.h>
#include <sys/socket.h>

定义函数:

  int sendto(int s, const void * msg, int len, unsigned int flags, const struct sockaddr * to, int tolen);

参数分析:

s --> 发送信息到那个socket
msg  --> 待发送的信息
len  --> 需要发送信息的长度
flags  --> flags 一般设 0, 其他数值定义如下:
	MSG_OOB 传送的数据以 out-of-band 送出.
	MSG_DONTROUTE 取消路由表查询
	MSG_DONTWAIT 设置为不可阻断运作
	MSG_NOSIGNAL 此动作不愿被 SIGPIPE 信号中断.
	to  --> 发送信息到哪个地址
tolen  --> 地址长度

返回值:

  • 成功则返回实际传送出去的字符数
    失败返回-1, 错误原因存于 errno 中.

====================================================================

6.数据缓存中涉及的问题:

(1) bzero ( 将一段内存内容全清为零 )

头文件:
#include <string.h>

定义函数:

  void bzero(void *s, int n);

函数说明:

  • bzero()会将参数 s 所指的内存区域前 n 个字节, 全部设为零值. 相当于调用 memset((void*)s, 0,size_tn);

(2) fgets ( 由文件中读取一字符串 )

头文件:
include<stdio.h>

定义函数:

  char * fgets(char * s, int size, FILE * stream);

函数说明:

  • fgets()用来从参数 stream 所指的文件内读入字符并存到参数 s 所指的内存空间, 直到出现换行字符、读到文件尾或是已读了 size-1 个字符为止, 最后会加上 NULL 作为字符串结束.

返回值:

  • gets()若成功则返回 s 指针, 返回 NULL 则表示有错误发生.

================================================================

服务器UDP代码:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>

#define  MSG_SIZE  1024


int main(int argc, char const *argv[])
{
    //创建一个套接字:
    int fd_socket = socket(AF_INET , SOCK_DGRAM , 0);
    //配置地址信息:
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(6520); //主机字节序转换为网络字节序
    addr.sin_addr.s_addr = inet_addr("192.168.162.129");
    //绑定地址信息:
    int addr_size = sizeof(addr);
    int ret = bind(fd_socket, (struct sockaddr *) &addr, addr_size);
    if(ret)
    {
        perror("bind error\n");
    }
    else
    {
        printf("bind succeed\n");
    }
    //等待来信:
    struct sockaddr_in from_addr;
    char *buf = malloc(MSG_SIZE);
    while(1)
    {
        bzero(buf,MSG_SIZE);
        recvfrom(fd_socket, buf, MSG_SIZE, 0,
                    (struct sockaddr *) &from_addr,
                            &addr_size);
        printf("%s \tIP:%s\t Port:%d\n\n", buf, 
                        inet_ntoa(from_addr.sin_addr),
                            ntohs(from_addr.sin_port));
    }


    return 0 ;
}
客户端UDP代码:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>

#define  MSG_SIZE  1024


int main(int argc, char const *argv[])
{
    //创建一个套接字:
    int fd_socket = socket(AF_INET , SOCK_DGRAM , 0);
    //配置地址信息:
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(6520); //主机字节序转换为网络字节序
    addr.sin_addr.s_addr = inet_addr("192.168.162.129");
    //发送信息:
    struct sockaddr_in from_addr;
    char *buf = malloc(MSG_SIZE);
    while(1)
    {
        bzero(buf,MSG_SIZE);
        fgets(buf, MSG_SIZE, stdin);
        int ret = sendto(fd_socket, buf, MSG_SIZE, 0,
                (struct sockaddr *) &addr, sizeof(addr));
        if(-1 == ret)
        {
            perror("send error\n");

        }
        else
        {
            printf("send succeed\n");
        }
    }


    return 0 ;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值