Linux学习笔记(4)socket收发消息原理剖析

Linux环境下“一切皆文件”,套接字被视为文件描述符,
1.创建套接字

#include <sys/type.h>
#include <sys/socket.h>
int socket(int domain,int type,int protocol);//成功创建返回一个文件描述符,否则返回-1
//1.domain:指示协议族的名字,如AF_INET为IPv4
//2.type:指示类型,如流式套接字SOCK_STREAM
//3.protocol:用于指示这种socket的具体协议类型,一般情况下设置为0。一个socket收发消息的原理

2.绑定IP地址
创建完套接字,套接字只是一个文件描述符,需要指定socket使用那个IP地址进行发送。

#include <sys/type.h>
#include <sys/socket.h>
int bind(int sockfd,const struct sockaddr *addr,socklen_t addrlen);
//sockfd:表示要绑定地址的套接字描述符。
//addr:绑定到套接字的地址。
//addrlen:绑定的地址长度。

3.客户端连接

#include <sys/type.h>
#include <sys/socket.h>
int connect(int sockfd,const struct sockaddr *addr,socklen_t addrlen);

connect的作用是用指定的套接字去连接指定的地址。
4.服务器端连接

#include <sys/type.h>
#include <sys/socket.h>
int listen(int sockfd,int backlog);
sockfd:成功创建的tcp套接字
backlog:定义tcp未处理连接的队列长度。

服务器端用listen来监听套接字。
在这里插入图片描述

//服务器端代码
  1# include <stdio.h>
  2 # include <stdlib.h>
  3 # include <assert.h>
  4 # include <string.h>
  5 # include <unistd.h>
  6 # include <sys/socket.h>
  7 # include <netinet/in.h>
  8 # include <arpa/inet.h>
  9 
 10 int main()
 11 {
 12     int sockfd = socket(AF_INET,SOCK_STREAM,0);//创建套接字
 13     assert(sockfd!=-1);
 14 
 15     struct sockaddr_in saddr,caddr;
 16     memset(&saddr,0,sizeof(saddr));
 17     saddr.sin_family = AF_INET;
 18     saddr.sin_port = htons(6000);
 19     saddr.sin_addr.s_addr =inet_addr("127.0.0.1 ");
 20 //15 16 17 18 19 定义专用的套接字端接口结构
 21     int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
 22     assert(res!=-1);
 23 
 24     listen(sockfd,5);
 25 
 26     while(1)
 27     {
 28         int len =sizeof(caddr);
 29         int c = accept(sockfd,(struct sockaddr*)&caddr,&len);
 30         if(c<0)
 31         {
 32             continue;
 33         }
 34         printf("c=%d,ip=%s,port=%d\n",c,inet_ntoa(caddr.sin_addr),ntohs(cadd    r.sin_port));
 35 
 36         char buff[128] = {0};
 37         recv(c,buff,127,0);
 38         printf("buff=%s\n",buff);
 39 
 40         send(c,"ok",2,0);
 41         close(c);
 42     }
 43 }
//客户端代码:
 1# include <stdio.h>
  2 # include <string.h>
  3 # include <stdlib.h>
  4 # include <unistd.h>
  5 # include  <sys/socket.h>
  6 # include <netinet/in.h>
  7 # include <arpa/inet.h>
  8 # include <assert.h>
  9 
 10 int main()
 11 {
 12     int sockfd = socket(AF_INET,SOCK_STREAM,0);
 13     assert(sockfd != -1);
 14 
 15     struct sockaddr_in saddr;
 16     memset (&saddr,0,sizeof(saddr));
 17     saddr.sin_family = AF_INET;
 18     saddr.sin_port = htons(6000);
 19     saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
 20 //15、16、17、18、19告诉客户端服务器端的ip和端口
 21     int res=connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));//connect成功则三次握手成功
 22     assert(res != -1);
 23 
 24     printf("input:\n");
 25     char buff[128]={0};
 26     fgets(buff,128,stdin);
 27 
 28     send(sockfd,buff,strlen(buff),0);
 29     memset(buff,0,128);
 30     recv(sockfd,buff,127,0);
 31     printf("buff=%s\n",buff);
 32 
 33     close(sockfd);
 34     exit(0);
 35 }

此客户端服务端只可以通信一次,多个客户端连接需要用多线程来处理。
在这里插入图片描述

服务器与客户端要想通信底层需要internet物理连接,网卡上配有IP地址和mac地址,服务端运行socket服务端程序,客户端运行socket客户端程序。
服务器通过网卡发送数据,内核态内存存放的操作系统可以操作底层的硬件。

猜你喜欢

转载自blog.csdn.net/qq_42111463/article/details/85608324