网络编程及其编程环境:
通信连接:
局域网拓扑图:
广域网拓扑图:
编程环境:vim,linux,.....
TCP和UDP编程模型
1,传输层TCP和UDP
1)OSI七层模型2)TCP协议 :传输控制协议,向用户进程提供可靠的全双工字节流
3)UDP协议:用户数据报协议,是一种无连接的协议,不可靠传输
2,TCP编程模型
1)客户端
2)服务器
例子1:socket()实现进程间通信,AF_UNIX
(1)服务器端;server.c
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/un.h>
int main()
{
int serverfd,clientfd;
struct sockaddr_un server,client;
int client_len=sizeof(client);
//initial
server.sun_family = AF_UNIX;
strcpy(server.sun_path,"mysocketunix");
//socket
serverfd=socket(AF_UNIX,SOCK_STREAM,0);
if(serverfd ==-1)
{
printf("create socket errror\n'");
exit(1);
}
//bind
if(bind(serverfd,(struct sockaddr *)&server,sizeof(server)) == -1)
{
printf("bind failure\n");
close(serverfd);
exit(1);
}
//listen
if(listen(serverfd,20)==-1)
{
printf("listen error\n");
close(serverfd);
exit(1);
}
printf("listening.......\n");
//accept
clientfd=accept(serverfd,(struct sockaddr *)&client,&client_len);
if(clientfd ==-1)
{
printf("accept error\n");
close(serverfd);
exit(1);
}
printf("accepted \n");
//operation
write(clientfd,"hello client !",14);
printf("had writed to client\n");
//close
close(serverfd);
close(clientfd);
return 0;
}
编译运行结果如下:
如图运行可执行文件后生成一个类似管道的文件mysocketunix
(1)客户端;client.c
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/un.h>
int main()
{
int clientfd;
struct sockaddr_un client;
char buf[100]={0};
//initial
client.sun_family = AF_UNIX;
strcpy(client.sun_path,"mysockunix");
//socket
clientfd=socket(AF_UNIX,SOCK_STREAM,0);
if(clientfd ==-1)
{
printf("create socket errror\n'");
exit(1);
}
//connect
if(connect(clientfd,(struct sockaddr *)&client,sizeof(client))==-1)
{
printf("connect error\n");
exit(1);
}
//operation
read(clientfd,buf,100);
printf("get message : %s\n",buf);
//close
close(clientfd);
return 0;
}
运行服务器./ser; 然后客户端连接./cli;结果如下图:
<1>等待客户端的连接
<2>客户端成功连接
例子2:socket()实现网络通信,AF_INET
服务器: server.c
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/un.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#define MAX_LISTEN 100
int main()
{
int server_fd,client_fd;
struct sockaddr_in server,client;
int client_len=sizeof(client);
//initial socket object
server.sin_family = AF_INET;
server.sin_addr.s_addr =htonl(INADDR_ANY);
server.sin_port =htons(8888);
//socket
server_fd=socket(AF_INET,SOCK_STREAM,0);
if(server_fd == -1)
{
printf("socket error\n");
exit(1);
}
//bind
if(bind(server_fd,(struct sockaddr *)&server,sizeof(server))==-1)
{
printf("bind error\n");
close(server_fd);
exit(1);
}
//listen
if(listen(server_fd,MAX_LISTEN)==-1)
{
printf("listen error\n");
close(server_fd);
exit(1);
}
printf("listening...........\n");
//accept
client_fd=accept(server_fd,(struct sockaddr *)&client,&client_len);
if(client_fd==-1)
{
printf("accept error\n");
close(server_fd);
exit(1);
}
//operation write or send
//write(client_fd,"hello client",12);
send(client_fd,"hello client",12);
//close
close(client_fd);
close(server_fd);
return 0;
}
客户端:client.c
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/un.h>
#include<netinet/in.h>
#include<arpa/inet.h>
int main()
{
struct sockaddr_in client;
int client_fd;
char read_buf[128];
//init
client.sin_family =AF_INET;
client.sin_addr.s_addr =inet_addr("192.168.0.122");
client.sin_port =htons(8888);
//socket
client_fd=socket(AF_INET,SOCK_STREAM,0);
if(client_fd==-1)
{
printf("socket error\n");
exit(1);
}
//connect
if(connect(client_fd,(struct sockaddr*)&client,sizeof(client))==-1)
{
printf("connect error\n");
close(client_fd);
exit(1);
}
//operation read or recv
//read(client_fd,read_buf,128);
recv(client_fd,read_buf,128,0);
printf("read_buf=%s\n",read_buf);
//close
close(client_fd);
return 0;
}
服务器server.c实现循环发送:
while(1)
{
//accept
client_fd=accept(server_fd,(struct sockaddr *)&client,&client_len);
if(client_fd==-1)
{
printf("accept error\n");
close(server_fd);
exit(1);
}
//operation write or send
//write(client_fd,"hello client",12);
send(client_fd,"hello client",12);
//close
close(client_fd);
}
客户端实现通过输入服务器主机名连接服务器,改进client.c内容如下:
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/un.h>
#include<netinet/in.h>
#include<arpa/inet.h>
int main(int argc,char *argv[])
{
if(argc<2)
{
printf("please input two argment\n");
exit(1);
}
struct hostent *myhost;
struct sockaddr_in client;
int client_fd;
char read_buf[128];
//init
client.sin_family =AF_INET;
myhost = gethostbyname(argv[1]);
if(!myhost)
{
printf("gethostname error\n");
exit(1);
}
client.sin_addr = *((struct in_addr *)myhost->h_addr);//hostname to addr
client.sin_port =htons(8888);
//socket
client_fd=socket(AF_INET,SOCK_STREAM,0);
if(client_fd==-1)
{
printf("socket error\n");
exit(1);
}
//connect
if(connect(client_fd,(struct sockaddr*)&client,sizeof(client))==-1)
{
printf("connect error\n");
close(client_fd);
exit(1);
}
//operation
//read(client_fd,read_buf,128);
recv(client_fd,read_buf,128,0);
printf("read_buf=%s\n",read_buf);
//close
close(client_fd);
return 0;
}
测试运行结果如下:
[注]不通过ip,而通过hostname来请求服务器;
有时候可能无法连接,是因为没有启动daytime服务,解决办法如下:
第一步:需要安装xinetd服务(其实daytime就包含在xinetd服务中)
第二部:修改/etc/xinetd.d/daytime文件.将此文件中的两个disable的值yes改为no.
第三步:注销一下系统或重启下xinetd服务
#/etc/init.d/xinetd restart
【注】字节转换函数(主机大端存储和网络小端存储之间的转换)
IP地址的转换函数
例子1:address convet to net和net convert to address
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main()
{
struct in_addr my_addr;
//convert address to network
inet_aton("192.168.0.120",&my_addr);
printf("address to network is:%d\n",my_addr.s_addr);
printf("network to address is :%s\n",inet_ntoa(my_addr));
return 0;
}
运行结果:
例子2;通过gethostbyname获取域名的主机IP
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
int main()
{
struct in_addr my_addr;
struct hostent *myhost;
//get host address by DNS Name
myhost = gethostbyname("www.baidu.com");
my_addr.s_addr =(uint32_t)(myhost->h_addr);
printf("www.baidu.com ip is : %s\n",inet_ntoa(my_addr));
return 0;
}
运行结果:
3)通信过程三次握手四次握手分析
4)其他基本编程知识
网络字节序
套接字地址结构
值-结果 传递地址结构长度
<1>进程---->内核
<2>内核---->进程
IP地址转换的相关函数
5)拓展时间服务的功能--各个函数解析
socket()函数
connect()函数
bind()函数
listen()函数
accept()函数
3,UDP编程模型
recvfrom函数
sendto函数
服务器和客户端
1,UDP服务器
server.c
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include<netinet/in.h>
#include<unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
int main(int argc,char *argv[])
{
struct sockaddr_in server_ip,client_ip;
socklen_t server_len,client_len;
int sd;
unsigned int rev;
int err;
char write_buf[128]={0},read_buf[128];
sd=socket(AF_INET,SOCK_DGRAM,0);//创建一个套接字
if(sd <0)
{
printf("create socket failure\n");
return -1;
}
//初始化服务器IP及Port等
bzero(&server_ip,sizeof(server_ip));//将对象清零,bzero比memset安全
server_ip.sin_family =AF_INET;//ipv4的协议族
server_ip.sin_port =htons(8888);//将主机数据转换为网络数据作为端口
server_ip.sin_addr.s_addr =htonl(INADDR_ANY);//本地主机IP作为服务器地址
memset(server_ip.sin_zero,0,8);//struct sockaddr_in的第三个参数
//绑定本机为服务器
err=bind(sd,(struct sockaddr*)&server_ip,sizeof(server_ip));
if(err<0)
{
printf("bind error\n");
close(sd);
return -2;
}
printf("bind success\n");
//获取客户端IP长度
client_len=sizeof(client_ip);
while(1)
{
//接收来自客户端的数据
rev=recvfrom(sd,read_buf,sizeof(read_buf),0,(struct sockaddr*)&client_ip,&client_len);
if(rev<0)
{
printf("recvform error\n");
close(sd);
return -3;
}
//打印客户端IP,端口Port及传过来的数据
printf("rev_len=%d\n",rev);
printf("client_ip=%s port=%d\n",inet_ntoa(client_ip.sin_addr),ntohs(client_ip.sin_port));
printf("client says: %s\n",read_buf);
//从标准输入向套接字读入数据
fgets(write_buf,sizeof(write_buf),stdin);
sendto(sd,write_buf,sizeof(write_buf),0,(struct sockaddr*)&client_ip,sizeof(client_ip));
bzero(&client_ip,client_len);//清零操作
bzero(write_buf,128);
bzero(read_buf,128);
}
close(sd);
return 0;
}
2,UDP客户端
client.c
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include<netinet/in.h>
#include<unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
int main(int argc,char *argv[])
{
int cd,rev;
struct sockaddr_in server_ip,client_ip;
socklen_t server_len,client_len;
char read_buf[128]={0};
char write_buf[128]={0};
cd=socket(AF_INET,SOCK_DGRAM,0);
if(cd<0)
{
printf("create socket failure\n");
return -1;
}
//因为一开始客户端没有recvfrom,故不知道server的IP和端口,
//这里需要自己初始化和绑定一次服务器的IP和端口
server_ip.sin_family =AF_INET;//服务器协议族
server_ip.sin_port =htons(8888);//服务器端口
inet_pton(AF_INET,"192.168.0.120",&server_ip.sin_addr.s_addr);//服务IP
memset(server_ip.sin_zero,0,8);//这行可以不写
while(1)
{
//从标准输入读取数据到读缓存
fgets(write_buf,128,stdin);
//将读缓存里的数据写到套接字,发送给客户端
sendto(cd,write_buf,sizeof(write_buf)+1,0,(struct sockaddr*)&server_ip,sizeof(server_ip));
//读取服务器发过来的数据
rev=recvfrom(cd,read_buf,sizeof(read_buf),0,NULL,NULL);
if(rev<0)
{
printf("recvfrom error\n");
close(cd);
return -2;
}
//打印服务器的IP和端口以及数据
printf("rev_len=%d\n",rev);
printf("client_ip=%s port=%d\n",inet_ntoa(server_ip.sin_addr),ntohs(server_ip.sin_port));
printf("server says : %s\n",read_buf);
}
close(cd);
return 0;
}
来源:CSDN
作者:I_T_I
链接:https://blog.csdn.net/weixin_38251305/article/details/104046066