初探socket 报式

1.socket

一般来说socket有一个别名也叫做套接字。

socket起源于Unix,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。Socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)。

说白了Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议,而不需要让用户自己去定义什么时候需要指定哪个协议哪个函数。

其实socket也没有层的概念,它只是一个facade设计模式的应用,让编程变的更简单。是一个软件抽象层。在网络编程中,我们大量用的都是通过socket实现的。
按照一切皆文件的设计原则 套接字描述符其实也就是一个整数,就是文件描述符

2.针对套接字的系统数据结构:

1)、套接字API里有个函数socket,它就是用来创建一个套接字。套接字设计的总体思路是,单个系统调用就可以创建任何套接字,因为套接字是相当笼统的。一旦套接字创建后,应用程序还需要调用其他函数来指定具体细节。例如调用socket将创建一个新的描述符条目:
在这里插入图片描述
2)、虽然套接字的内部数据结构包含很多字段,但是系统创建套接字后,大多数字字段没有填写。应用程序创建套接字后在该套接字可以使用之前,必须调用其他的过程来填充这些字段。
在这里插入图片描述
详细介绍

3.一个demo

协议头文件

#define NAMESIZE 11

#include <stdint.h>

//指定接收的端口号
#define RCVPORT 1989

//要发送的结构体
struct msg_st
{
		//不能用char int 因为环境不同
        uint8_t name[NAMESIZE];
        uint32_t math;
        uint32_t eng;

}__attribute((packed));//防止内存对齐
//因为是跨主机 你不知道对方主机的对齐格式
#endif

rcver.c

#define SIZE 40 



int main()
{
   int sd;//socket 套接字
   struct sockaddr_in laddr , raddr;
   struct msg_st buf;
   socklen_t raddr_len;
   char ipstr[SIZE];

	//创建一个socket套接字
	//IPV4协议族 中的UDP协议 来传输数据报
   sd = socket(AF_INET, SOCK_DGRAM, 0/*IPPROTO_UDP*/);
   if(sd < 0)
   {
           perror("socket()");
           exit(1);
   }

   laddr.sin_family = AF_INET;//协议族
   laddr.sin_port = htons(RCVPORT);//端口号
   inet_pton(AF_INET, "0.0.0.0", &laddr.sin_addr);
   //ip地址转化成大整数

	//将socket套接字 和 ip端口号进行绑定
   if(bind(sd, (void*)&laddr, sizeof(laddr)) < 0)
   {
           perror("bind()");
           exit(1);
   }

   /*!!!!!*/
   raddr_len = sizeof(raddr);

   while(1)
   {
   			//开始接受数据
   			//从socket套接字 放到buf中 指定buf大小
   			//由于是无连接 所以发送端口的信息回填到raddr中
           recvfrom(sd, &buf, sizeof(buf), 0, 
           (void *)&raddr, &raddr_len);
           
           //把addr里面的ip大整数变成字符串
           inet_ntop(AF_INET, &raddr.sin_addr, ipstr, SIZE);
           
           //进行输出 注意网络字节序的问题
           printf("MSG FROM **** %s:%d*****\n", 
           ipstr, ntohs(raddr.sin_port));
           
           printf("NMAE = %s\n", buf.name);
           
           printf("MATH = %d Eng = %d\n", 
           ntohl(buf.math), ntohl(buf.eng));
   }

   close(sd);

   return 0;
}

snder.c
发送方不用绑定一个端口 bind


int main(int argc, char *argv[])
{
   int sd;
   struct sockaddr_in  raddr;
   struct msg_st buf;

   if(argc < 2)
   {
           fprintf(stderr, "No Enough\n");
           exit(1);
   }


	//也是获取一个socket套接字
   sd = socket(AF_INET, SOCK_DGRAM, 0);
   if(sd < 0)
   {
           perror("socket()");
           exit(1);
   }

	//初始化要发送的对象 注意字节序
   strcpy(buf.name, "ZHUZHENGHUA");
   buf.math = htonl(rand()%100);
   buf.eng = htonl(rand()%100);

   raddr.sin_family = AF_INET;//协议族
   raddr.sin_port = htons(RCVPORT);//目标端口
   inet_pton(AF_INET, argv[1], &raddr.sin_addr);//目的ip

//发送 套接字 要发送的东西 发送的地址
   if(sendto(sd, &buf, sizeof(buf), 0, (void*)&raddr, sizeof(raddr)) < 0)
   {
           perror("sendto()");
           exit(1);
   }

   puts("OK");

   close(sd);

   return 0;
}
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值