1.tcp/ip 协议
上层为应用层,下层为底层
2.tcp通信
服务器:
(1)建立套接字 socket(int domain, int type, int protocol);
第一个参数:指定域,协议族
AF_UNIX, AF_LOCAL Local communication unix(7) 建立UNIX的协议
AF_INET IPv4 Internet protocols ip(7) 这个代表使用IPV4的协议族 ----> 32bit
AF_INET6 IPv6 Internet protocols ipv6(7) 这个代表使用IPV6的协议族 ----> 128bit
第二个参数:指定我们创建的套接字的类型
SOCK_STREAM 提供一种有序的、可靠、双向的,基于连接的字节流类型的一种套接字。 ----> TCP
SOCK_DGRAM 提供一种数据报的通讯方式,这种方式是无连接的,不可靠的,有固定最大数据通讯长度的这一种套接字 ----> UDP
第三个参数:指定该套接字用这个协议族里面的哪个子协议。一般都用0。
返回值:如果成功这个新建的套接字的fd,就会返回。如果出错就会返回-1。
(2)绑定: bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
第一个参数:就是前面返回的文件描述符。
第二个参数:指定我们通讯的地址,这个是一个通用的结构体,它的地址,由指定的协议族去决定的。
第三个参数:指定的是第二个参数地址的大小。
通用的结构体:
struct sockaddr {
sa_family_t sa_family; //指定所用的协议族。
char sa_data[14]; //这里是具体的地址填充的空间。
}
在头文件里面:#include <netinet/in.h>
typedef uint32_t in_addr_t; //表示其IP地址
struct in_addr
{
in_addr_t s_addr; //这个IP地址,实际上是一个32位无符号的数据
};
描述我们网络socket地址 /* Structure describing an Internet socket address. */
typedef uint16_t in_port_t; //16位的端口号
struct sockaddr_in
{
__SOCKADDR_COMMON (sin_); //协议族
in_port_t sin_port; //端口号 2字节
struct in_addr sin_addr; //IP地址 4字节
unsigned char sin_zero[8]; //填充8个字节,使其和其他的协议族的地址结构体大小一致。
};
端口号:
小端的保存方式,低地址保存低位的数据。
大端的保存方式,低地址保存高位的数据。
#include <arpa/inet.h>
h-->host(主机)
n-->network(网络)
l-->代表是32位
s-->代表是16位
htonl();
htons();
ntohl();
ntohs();
(3)监听 listen(int sockfd, int backlog);
第一个参数:前面新建的fd。
第二个参数:监听队列上最大的请求数。
(4)接受链接 accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
第一个参数:前面新建的fd。
第二个参数:用来保存客户端的地址信息。
第三个参数:用来保存客户端地址的长度。
返回值:成功的话返回一个新的fd,然后服务器就可以通过这个新的fd和客户端进行通讯。如果失败返回 -1;
(5)对数据的操作(收,发)
(6)关闭
客户端:
1.建立套接字
2.链接服务器
connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
第一个参数:就是第一步新建的socket返回的fd。
第二个参数:指定你要链接的服务器的地址(IP+PORT)
第三个参数:这个地址的长度。
3.对数据操作(收,发)
4.关闭
今日代码:
/*************************************************************************
> File Name: server1.c 服务器
> Author: csgec
> Mail: [email protected]
> Created Time: Tue 31 Jul 2018 03:50:36 PM HKT
************************************************************************/
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string.h>
int main()
{
int serverfd;
int clientfd;
int ret;
serverfd = socket(AF_INET,SOCK_STREAM,0);//建立套接字
if(serverfd < 0)
{
perror("socket crate fail\n");
return -1;
}
struct sockaddr_in serveraddr;
struct sockaddr_in clientaddr;
memset(&serveraddr,0,sizeof(serveraddr));
memset(&serveraddr,0,sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = INADDR_ANY;//ip地址,表示接受任意ip的请求
serveraddr.sin_port = htons(8000);//表示对应的端口号,客户端就可以通过这个端口通讯
//绑定通讯地址
ret = bind(serverfd,(struct sockaddr *)&serveraddr,sizeof(struct sockaddr_in));
if(ret < 0)
{
perror("bind fail");
return -1;
}
//监听
ret = listen(serverfd,10);
if(ret < 0)
{
perror("listen fail");
return -1;
}
int sin_size = sizeof(struct sockaddr_in);
//接受链接
clientfd = accept(serverfd,(struct sockaddr *)&clientaddr,&sin_size);
if(clientfd < 0)
{
perror("accept faile");
close(serverfd);
return -1;
}
char buf[128];
memset(buf,0,128);
while(1)//对数据收发操作
{
printf("请给客户机发一条消息:");
scanf("%s",buf);
send(clientfd,buf,strlen(buf),0);
memset(buf,0,128);
recv(clientfd,buf,128,0);
printf("客户机回复说:");
printf("%s\n",buf);
if(strcmp(buf,"quit") == 0)
{
break;
}
}
close(serverfd);
close(clientfd);
}
/////////////////////////////////////////////////////////////////////////////
/*************************************************************************
> File Name: kehuji1.c 客户机
> Author: csgec
> Mail: [email protected]
> Created Time: Tue 31 Jul 2018 03:50:36 PM HKT
************************************************************************/
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string.h>
int main()
{
int serverfd;
int clientfd;
int ret;
serverfd = socket(AF_INET,SOCK_STREAM,0);//建立套接字
if(serverfd < 0)
{
perror("socket crate fail\n");
return -1;
}
struct sockaddr_in serveraddr;
memset(&serveraddr,0,sizeof(serveraddr));//清空结构体
//初始化
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = INADDR_ANY;//ip地址,表示接受任意ip的请求
serveraddr.sin_addr.s_addr = inet_addr("127.0.0.1");//ip地址,表示接受任意ip的请求
serveraddr.sin_port = htons(8000);//表示对应的端口号,客户端就可以通过这个端口通讯
ret = connect(serverfd,(struct sockaddr *)&serveraddr,sizeof(struct sockaddr));
if(ret < 0)
{
perror("connect fail\n");
close(serverfd);
return -1;
}
char buf[128];
memset(buf,0,128);
while(1)//对数据收发操作
{
printf("收到服务器的数据为:");
recv(serverfd,buf,128,0);
printf("%s\n",buf);
memset(buf,0,128);
printf("请给服务器回信:");
scanf("%s",buf);
send(serverfd,buf,strlen(buf),0);
if(strcmp(buf,"quit") == 0)
{
break;
}
}
close(serverfd);
}