服务器与客户端的概念:
服务器: 在一次通讯中,提供数据的为服务器
客户端: 在一次通讯中,获取数据的为客户端
协议的选择(两种不同的协议有两种不同的编程方式):
TCP: 面向连接的(不断发送数据)可靠的(数据完整,例如银行交易往来数据) 流式服务
UDP: 无连接(间断发送数据) 不可靠的(可能会有数据丢失,例如视频数据) 数据报服务
关于TCP 的编程流程:
server: socket(打开网络接口) bind(将服务器的IP地址与端口号与socket绑定) listen(监听连接) accept(拿出一个连接) recv/send(收发数据) close(关闭连接)
client: socket /*bind*/(可要可不要) connect(发起连接) recv/send close
int socket(int domain, int type, int protocol);
domain:: 协议簇 AF_INET
type:: 选择协议 SOCK_STREAM(tcp) SOCK_DGRAM(udp)
protocol:: 0
int bind(int sockfd, struct sockaddr *addr, int addrlen);
addr:: 指定 IP 地址和端口号
addrlen::地址长度
struct sockaddr_in
{
sa_family_t sin_family; // 地址簇 AF_INET
u_int16_t sin_port ; // 端口号 网络字节序(大端模式) PC 机(小端模式)
struct in_addr sin_addr; // IP 地址
}
struct in_addr
{
u_int32_t s_addr; // IP 地址最终的表示
}
int listen(int sockfd, int size);
int accept(int sockfd, struct sockaddr *addr, int *addrlen); //可能会阻塞
返回值: 失败返回-1,成功返回获取到的和客户端连接的文件描述符
addr:: 记录客户端的 IP 地址和端口号
int connect(int sockfd, struct sockaddr* addr, int addrlen);
addr:: 要连接的服务器的 IP 地址和端口号
命令:netstat -atp 显示本机上所有的 TCP 服务程序以及其占用的端口号
具体实现代码:
服务器:
#include
#include
#include
#include
#include
#include
#include
#include
void main()
{
int sockfd=socket(AF_INET,SOCK_STREAM,0);
assert(sockfd!=-1);
struct sockaddr_in ser,cli;
ser.sin_family=AF_INET;//地址簇
ser.sin_port=htons(6000);//端口号,5000以内的不用 htons 主机转网络short模式
ser.sin_addr.s_addr=inet_addr("127.0.0.1"); //inet_addr完成类型转化 字符串类型转换成无符号整形 点分十进制
int res=bind(sockfd,(struct sockaddr*)&ser,sizeof(ser)); //第二个参数获取客户端地址
assert(res!=-1);//崩溃要么地址不对,要么端口号正在被使用或无权限
listen(sockfd,5);//监听哪个套接字 5创建队列大小
int len=sizeof(cli);
int c=accept(sockfd,(struct sockaddr*)&cli,&len);//第二个参数保存获取的端口号和IP地址 失败返回-1,成功拿出一个连接
assert(c!=-1);
char buff[128]={0};
recv(c,buff,127,0); //获取的对象、数据、多少字节、属性
printf("recv::%sn",buff);
send(c,"i know",strlen("i know"),0);
close(c);
close(sockfd);
}
客户端:
#include
#include
#include
#include
#include
#include
#include
#include
void main()
{
int sockfd=socket(AF_INET,SOCK_STREAM,0);
assert(sockfd!=-1);
struct sockaddr_in ser,cli;
ser.sin_family=AF_INET;
ser.sin_port=htons(6000);//服务器的端口号
ser.sin_addr.s_addr=inet_addr("127.0.0.1");
int res=connect(sockfd,(struct sockaddr*)&ser,sizeof(ser));//
assert(res!=-1);
send(sockfd,"hello world",strlen("hello world"),0);
char buff[128]={0};
recv(sockfd,buff,127,0);
printf("recv::%sn",buff);
close(sockfd);
}
运行时先运行服务器后运行客户端,运行结果如下: