Unix C (十)
来源:互联网 发布:必备的办公软件 编辑:程序博客网 时间:2024/06/05 10:41
ip 地址 是网络中计算机的地址,和mac地址(网卡出厂地址/物理地址)联合 能够让网络找到计算机。用端口(port)定位一个进程。因此网络编程就是 ip+端口。
Unix系统中,几乎一切都可以看成文件。因此网络信息的交互就用文件的交互方式。
ip地址底层是整数,分为ipv4(4位ip)和ipv6(6位)。
对ip的描述方式一般使用点分十进制。4个或者6个 0-255的数字,并用 . 分开。底层ipv4其实就是一个32位二进制。
在网络中,字节顺序固定,但本机中,可能从低到高,也可能从高到低。
0-1023 尽量不用,系统会非连续的使用
1024-48XXX 使用,固有端口
48XXX-65535 不要使用,动态端口(不稳定)
编程:
1 socket套接字
socket 编程 分类:
一对一(点对点)
一对多(多个客户端/一个服务器)
支持TCP/UDP传输
1.1 一对一本地通信
a 服务端
1) 创建一个socket
int socket(int domain,int type,int protocol)
domain: 域 ,选择协议簇
PF_UNIX / PF_LOCAL / PF_FILE (PF换AF)
本地通信(进程间通信)
PF_INET/AF_INET 网络通信(IPV4)
PF_INET6/AF_INET6 网络通信(IPV6)
type : 通信协议的类型
SOCK_STREAM : 数据流(TCP)
SOCK_DGRAM :数据报(UDP)
protocol : 本来应该是选协议,但基本没用,因为协议由前2个参数决定
返回值是一个整数,socket描述符。socket描述符类似文件描述符,read读,write写。
2) 准备通信地址
参数通信地址(只是做参数,不会真正使用)
struct sockaddr{
int sa_family;//协议簇
char sa_data[];//地址
};
本地通信地址(文件):
struct sockaddr_un{ // sys/un.h
int sun_family;//协议簇
char sun_path[];//文件名
};
实例:
(1)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <string.h>
int main(){
//创建通信描述符
int sockfd = socket(PF_UNIX,SOCK_DGRAM,0);
if(sockfd == -1)
perror("socket"),exit(-1);
//准备本地通新地址
struct sockaddr_un addr;
addr.sun_family = PF_UNIX;
strcpy(addr.sun_path,"a.sock");
//连接
int res = connect(sockfd,(struct sockaddr*)&addr,sizeof(addr));
if(res == -1)
perror("bind"),exit(-1);
printf("connect ok\n");
//写内容
write(sockfd,"hello socket!",13);
printf("成功写出\n");
//关闭描述符
close(sockfd);
return 0;
}
(2)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <string.h>
int main(){
//创建通信描述符
int sockfd = socket(PF_UNIX,SOCK_DGRAM,0);
if(sockfd == -1)
perror("socket"),exit(-1);
//准备本地通信地址
struct sockaddr_un addr;
addr.sun_family = PF_UNIX;
strcpy(addr.sun_path,"a.sock");
//绑定
int res = bind(sockfd,(struct sockaddr*)&addr,sizeof(addr));
if(res == -1)
perror("bind"),exit(-1);
printf("bind ok\n");
//读取内容
char buf[100] = {};
read(sockfd,buf,sizeof(buf));
printf("读到了:%s\n",buf);
//关闭描述符
close(sockfd);
return 0;
}
struct sockaddr_in{ // netinet/in.h
int sin_family;//协议簇
short sin_port;//端口
struct in_addr sin_addr;//IP
};
网络编程:
基于TCP的编程步骤:
Server端:
1 socket()
2 准备通信地址 struct sockaddr_in
3 绑定 bind()
4 listen()
5 accept(),返回一个用于交互的新的描述符
6 读写 read() write()
7 关闭close()
Client端:
1 socket()
2 准备通信地址 struct sockaddr_in
3 连接 connect()
4 读写 read() write()
5 关闭close()
基于UDP的编程步骤:
接收方:
1 socket()
2 准备通信地址,struct sockaddr_in
3 绑定 bind()
4 发送或接收 sendto() recvfrom() read()
5 关闭close()
发送方:
1 socket()
2 准备通信地址,struct sockaddr_in
3 发送或接收 sendto() recvfrom() read()
4 关闭close()
实例:
TCP通信
(1)服务端
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
//实现一对多
void fa(int signo){
printf("服务器即将退出\n");
//sleep(1);
exit(0);
}
int main(){
signal(SIGINT,fa);
//1 创建socket,accept不支持UDP
int sockfd = socket(PF_INET,SOCK_STREAM,0);
if(sockfd == -1) perror("socket"),exit(-1);
//2 准备通信地址
struct sockaddr_in addr;
addr.sin_family = PF_INET;
addr.sin_port = htons(2222);
addr.sin_addr.s_addr = inet_addr("172.40.0.65");
//addr.sin_addr.s_addr = INADDR_ANY;//本机ip
//防止地址已经使用
int reuseaddr = 1;
setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&reuseaddr,sizeof(reuseaddr));
//3 绑定
int res = bind(sockfd,(struct sockaddr*)&addr,sizeof(addr));
if(res == -1) perror("bind"),exit(-1);
printf("bind ok\n");
//4 监听
if(listen(sockfd,100)==-1)perror("list"),exit(-1);
printf("listen........\n");
//5 等待客户端的连接
while(1){
struct sockaddr_in clientaddr;
socklen_t len = sizeof(clientaddr);
int fd = accept(sockfd,//阻塞,直到客户端连接
(struct sockaddr*)&clientaddr,&len);
if(fd == -1) perror("accept"),exit(-1);
char *ip = inet_ntoa(clientaddr.sin_addr);//转换
printf("客户端%s连接了服务器\n",ip);
pid_t pid = fork();
if(pid == 0){
//6 用fd进行信息交互
while(1){
char buf[100] = { };
if(read(fd,buf,100)==-1)
perror("read"),exit(-1);
printf("读到了:%s\n",buf);
write(fd,buf,strlen(buf));
}
close(fd);//练习:用信号在关闭服务器时打印信息
exit(0);
}
}
//close(sockfd);//7 关闭
}
(2)客户端:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
int main(){
//创建网络通信描述符
int sockfd = socket(PF_INET,SOCK_STREAM,0);
if(sockfd == -1)
perror("socket"),exit(-1);
//准备通信地址
struct sockaddr_in addr;
addr.sin_family = PF_INET;
addr.sin_port = htons(2222);
addr.sin_addr.s_addr = inet_addr("172.40.0.65");
//addr.sin_addr.s_addr = INADDR_ANY;//本机ip
//连接服务器
int res = connect(sockfd,(struct sockaddr*)&addr,
sizeof(addr));
if(res == -1) perror("connect"),exit(-1);
//通信
while(1){
char bufscan[100] = {};
printf("请输入要说的话\n");
scanf("%s",bufscan);
res = write(sockfd,bufscan,strlen(bufscan));
if(res == -1)
perror("write"),exit(-1);
if(strcmp(bufscan,"bye")==0) break;
char buf[100] = {};
res = read(sockfd,buf,100);
if(res == -1)
perror("read"),exit(-1);
printf("读到了:%s\n",buf);
}
close(sockfd);
}
UDP通信
(1)服务端
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
int main(){
//创建网络通信描述符
int fd = socket(AF_INET,SOCK_DGRAM,0);
if(fd==-1)
perror("socket"),exit(-1);
//准备通信地址
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(2222);
addr.sin_addr.s_addr = inet_addr("172.40.0.11");
//绑定
int res = bind(fd,(struct sockaddr*)&addr,sizeof(addr));
if(res==-1)
perror("bind"),exit(-1);
printf("bind ok\n");
//通信
char buf[100] = {};
struct sockaddr_in from;
socklen_t length = sizeof(from);
int len = recvfrom(fd,buf,sizeof(buf),0,(struct sockaddr*)&from,&length);
printf("读到%d字节,内容:%s\n",len,buf);
sendto(fd,"welcome",7,0,(struct sockaddr*)&from,length);
//关闭描述符
close(fd);
return 0;
}
(2)客户端
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
int main(){
//创建通信描述符
int fd = socket(AF_INET,SOCK_DGRAM,0);
if(fd==-1)
perror("socket"),exit(-1);
//准备通信地址
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(2222);//服务端口
addr.sin_addr.s_addr =inet_addr("172.40.0.11");
//UDP无连接协议,理应不connect就能发送
//int res = write(fd,"hello",5);
//通信
int res = sendto(fd,"hello",5,0,(struct sockaddr*)&addr,sizeof(addr));
if(res==-1)
perror("write"),exit(-1);
char buf[100] = {};
read(fd,buf,sizeof(buf));
printf("buf=%s\n",buf);
close(fd);
return 0;
}
- Unix C (十)
- Unix学习(十)
- UNIX网络编程--广播(二十)
- UNIX环境高级编程--信号(十)
- UNIX网络编程(十)Posix信号量
- UNIX网络编程--广播(二十)
- UNIX环境高级编程(十)信号
- Unix C (一)
- Unix C (二)
- Unix C (三)
- Unix C (四)
- Unix C (五)
- Unix C (六)
- Unix C (七)
- Unix C (八)
- Unix C (九)
- Unix C (十一)
- Unix C杂谈(笔记)
- centOS+bochs+gdb调试linux0.11
- 第十七周项目7-电子词典结构体版
- rake 是什么
- Android 关于videoview 弹窗 “抱歉,无法播放此视频”
- 蓝桥杯试题集 基础练习 回文数
- Unix C (十)
- javascript跨框架显示div
- ios:UIAlertView自动消失
- Unity碰撞检测
- CHM 已取消到该网页的导航
- Java通信之Socket网络编程
- [BuildRelease]跨平台构建工具Cmake
- IOS调试技巧:当程序崩溃的时候怎么办 iphone IOS
- 第17周项目6-学生成绩统计3(1)