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客户端程序。
服务器通过网卡发送数据,内核态内存存放的操作系统可以操作底层的硬件。