Socket编程-④udp代码实例+解析

( 2018年11月29日 )

补充知识点

1.套接字

  • 源IP地址和目的IP地址以及源端口号和目的端口号的组合称为套接字。
  • 其用于标识客户端请求的服务器和服务

2.地址结构sockaddr和sockaddr_in的区别

  • 结构体struct sockaddr在/usr/include/linux/socket.h中定义

  • 结构体struct sockaddr_in在/usr/include/netinet/in.h中定义(IPv4地址结构)

  • 对比总结:
    struct sockaddr是通用的套接字地址,而struct sockaddr_in则是internet环境下套接字的地址形式,两个结构体一样大,16个字节,都有family属性,不同的是:sockaddr用其余14个字节来表示sa_data,而sockaddr_in把14个字节拆分成sin_port, sin_addr和sin_zero分别表示端口、ip地址。sin_zero用来填充字节使sockaddr_in和sockaddr保持一样大小。sockaddr和sockaddr_in包含的数据都是一样的,但他们在使用上有区别:
    程序员不应操作sockaddr,需要把sockaddr_in结构强制转换成sockaddr结构再传入系统调用函数中,sockaddr是给操作系统用的程序员应使用sockaddr_in来表示地址,sockaddr_in区分了地址和端口,使用更方便。

  • 例:

    int sockfd;
    struct sockaddr_in my_addr;
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    my_addr.sin_family = AF_INET; /* 主机字节序 */
    my_addr.sin_port = htons(MYPORT); /* short, 网络字节序 */
    my_addr.sin_addr.s_addr = inet_addr("192.168.0.1");
     bzero(&(my_addr.sin_zero), 8); /* zero the rest of the struct */
    //memset(&my_addr.sin_zero, 0, 8);
    bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr));
    

3.exit()、fork() - 基于 Linux

exit()

  • 在Linux系统下,return是程序返回,而exit()函数是程序结束标识,
    参数为0时,即exit(0)表示程序正常退出,非0表示非正常退出,但
    具体是1还是-1,没有特别的规定,可以自己定义其含义。

fork()
在Linux中fork函数是非常重要的函数,它的作用是从已经存在的进程中创建一个子进程,而原进程称为父进程。

#include<unistd.h>//引用fork时的头文件
pid_t   fork(void);//fork的返回类型为空1

在这里插入图片描述

  • 调用fork(),当控制转移到内核中的fork代码后,内核开始做:
    1.分配新的内存块和内核数据结构给子进程。
    2.将父进程部分数据结构内容拷贝至子进程。
    3.将子进程添加到系统进程列表。
    4.fork返回开始调度器,调度。

    #include<stdio.h>
    #include<unistd.h>
    #include<stdlib.h>
    int main()
    {
      pid_t pid;
      printf("before :pid is %d\n",getpid());
      if((pid=fork())==-1)
      perror("fork()"),exit(1);
      printf("After:pid=%d,fork return %d\n",getpid(),pid);
      sleep(1);
      return 0;
      }
    

·调用一次,返回两次
fork函数被父进程调用一次,但是却返回两次;一次是返回到父进程,一次是返回到新创建的子进程。
在这里插入图片描述

·注意
•并发执行
子进程和父进程是并发运行的独立进程。内核能够以任意的方式交替执行他们的逻辑控制流中的指令。在我们的系统上运行这个程序时,父进程先运行它的printf语句,然后是子进程。
•相同但是独立的地址空间
因为父进程和子进程是独立的进程,他们都有自己私有的地址空间,当父进程或者子进程单独改变时,不会影响到彼此,类似于c++的写实拷贝的形式自建一个副本。
•fork的返回值
1.fork的子进程返回为0;
2.父进程返回的是子进程的pid。
•fork的常规用法
1.一个父进程希望复制自己,使得子进程同时执行不同的代码段,例如:父进程等待客户端请求,生成一个子进程来等待请求处理。
2.一个进程要执行一个不同的程序。
•fokr调用失败的原因
1.系统中有太多进程
2.实际用户的进程数超过限制

◎解析代码◎

在这里插入图片描述

Socket_demo _udp

实验路径**/home/rain/Socket_exp/Socket_UDP_demo 实验环境 - Linux

ser.c - 建立socket服务器

//头文件:
stdio.hunistd.hsys/types.hsys/socket.harpa/inet.h
//定义端口号:PORT - ( 0 - 65535 ) - 1024以下端口号保留预定义服务

1.创建Socket对象

int socket_fd = socket( AF_INET , SOCK_DGRAM , 0 )
if( socket_fd == -1 )
{
printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);
//OR  perror("socket failed");
exit(-1);  
}

2.创建网络通信对象

struct sockaddr_in addr;
addr.sin_family =AF_INET;
addr.sin_port =htons(PORT);
addr.sin_addr.s_addr=inet_addr("192.168.18.136");
//OR  addr.sin_addr.s_addr=inet_addr("127.0.0.1");

3.绑定socket对象与通信连接

int ret =bind(socket_fd,(struct sockaddr*)&addr,sizeof(addr));
if(0>ret)
{
    printf("bind\n");
    return -1;
 }

4.交换数据

struct sockaddr_in cli;
socklen_t len=sizeof(cli);
char buf[4096] = {0};char p[] = "Successful receipt\n";char *s = p;
while(1)
{
recvfrom(socket_fd,&buf,sizeof(buf),0,(struct sockaddr*)&cli,&len);
printf("recv : %s\n",buf);
sendto(socket_fd,&p,sizeof(p),0,(struct sockaddr*)&cli,len);
 }
 close(socket_fd);

cli.c - 建立socket客户端

//头文件:
stdio.hunistd.hsys/types.hsys/socket.harpa/inet.h
//定义端口号:PORT - ( 0 - 65535 ) - 1024以下端口号保留预定义服务

1.创建Socket对象

int sockfd=socket(AF_INET,SOCK_DGRAM,0); /*建立数据报套接字*/

2.创建网络通信对象

struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr)); /*清空地址结构*/
addr.sin_family =AF_INET;/*地址类型为AF_INET*/
addr.sin_port =htons(PORT);
addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //IP-> 服务器

3.交换数据

printf("Input:");
char buf[4096]={0}; scanf("%s",buf);
sendto(sockfd,&buf,sizeof(buf),0,(struct sockaddr*)&addr,sizeof(addr));
socklen_t len=sizeof(addr);
inr i = recvfrom(sockfd,&buf,sizeof(buf),0,(struct sockaddr*)&addr,&len);
if(i !=-1)
{ printf(" server 成功接受\n"); }
else
 { printf("server 数据丢失\n");}
printf("服务器返回数据 : %s\n",buf);
close(sockfd);

//注:可参照Socket编程-③tcp代码实例+解析,运用main函数参数,实现合理化进入
·socket_fd - /套接字文件描述符/

工程代码
在这里插入图片描述
在这里插入图片描述
https://download.csdn.net/download/qq_42819325/89139735

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值