现在的位置: 首页 > 综合 > 正文

socket编程(1)

2017年06月18日 ⁄ 综合 ⁄ 共 3464字 ⁄ 字号 评论关闭

网络编程就是用IP地址定位计算机,用端口定位对应的进程。

端口是16位二进制的整数0-65535.其中:0-1023基本不用,被系统松散的占用。比如:

80 HTTP的端口(可以改)

21 FTP端口

23 Telnet端口

1024 - 48xxx+可用端口,某些软件安装后会占用某些特定端口,比如:

1521 oracle的监听端口

8080 oracle的http server

7001 weblogic服务器占用的端口(Java服务器)

......

48000+ -- 65535不稳定端口,随时可能被系统拿去做临时的端口

整数在存储时,本机有两种可能性,从低字节到高字节和从高字节到低字节,就是所谓的小端格式和大端格式,但在网络中,字节顺序是唯一的。因此,本机字节顺序和网络字节顺序有可能不一致,htons函数用于整数的本机器格式转网络。

Linux下网络编程C提供了比较完整的函数和变量的支持。

网络通信包括一对一(点对点)和一对多。一对一分为本地通信(IPC)和网络通信,本地通信(两个本地进程)使用文件做交互的媒介,后缀是.sock,类型为s。

一对一通信的步骤:
1、服务端
1.1 创建一个socket,函数socket(),返回socket描述符。
int socket(int domain,int type,int protocol)
参数domain:域用于选择协议族,本地通信/网络
AF_UNIX AF_LOCAL AF_FILE --- 本地通信
AF_INET --- 网络通信(IPV4)
AF_INET6 --- 网络通信(IPV6)
注:AF换成PF也是一样的。
参数type:选择通信方式,同时确定协议
SOCK_STREAM --- 数据流,针对TCP协议
SOCK_DGRAM --- 数据报,针对UDP协议
参数protocol基本用不到,因为协议前2个参数已经确定了,一般给0即可。
返回socket描述符,失败返回-1。socket描述符用法和文件 描述符一样。
1.2 准备通信地址(本地是文件/网络是IP+端口)
通信地址有三个结构组成:
struct sockaddr{
int sa_family;//协议族
char sa_data[];//通信地址
};
这个结构里面的成员无需记忆,因为这个结构只用来做函数的参数类型,从不用来存储数据。这个结构的类型用于兼容本地通信地址和网络通信地址。
本地通信地址用:
#include<sys/un.h>
struct sockaddr_un{
int sun_family;//协议族,和domain一致
sun_path[];//带路径的socket文件名
};
网络通信地址用:
#include<netinet/in.h>
struct sockaddr_in{
int sin_family;
short sin_port;//端口号
struct in_addr sin_addr;//IP地址
};
1.3 绑定socket和通信地址
bind(int sock,addr,sizeof(addr))
1.4 通信 --- read write
1.5 关闭  --- close
2、客户端
2.1 创建socket
2.2 准备通信地址,如果是网络,准备的是服务器通信地址。
2.3 连接服务器,函数connect(),用法和bind()完全一样。
2.4 通信 --- 与服务端交叉进行。
2.5 关闭。

一对一本地通信:

server.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/socket.h>
#include<sys/un.h>

int main(){
	int sockfd = socket(AF_UNIX,SOCK_DGRAM,0);
	if (sockfd == -1){
		perror("socket"),exit(-1);
	}
	struct sockaddr_un addr;
	addr.sun_family = AF_UNIX;
	strcpy(addr.sun_path,"a.sock");
	int res = bind(sockfd,(struct sockaddr*)&addr,
			sizeof(addr));
	if (res == -1){
		perror("bind"),exit(-1);
	}
	printf("绑定成功\n");
	char buf[100] = {};
	res = read(sockfd,buf,100);
	printf("读到了%d字节,内容:%s\n",res,buf);
	close(sockfd);
	return 0;
}

client.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/socket.h>
#include<sys/un.h>

int main(){
	int sockfd = socket(AF_UNIX,SOCK_DGRAM,0);
	if (sockfd == -1){
		perror("socket"),exit(-1);
	}
	struct sockaddr_un addr;
	addr.sun_family = AF_UNIX;
	strcpy(addr.sun_path,"a.sock");
	int res = connect(sockfd,(struct sockaddr*)&addr,
			sizeof(addr));
	if (res == -1){
		perror("connect"),exit(-1);
	}
	printf("连接成功\n");
	write(sockfd,"hello",5);
	close(sockfd);
	return 0;
}

一对一网络通信:

server.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>//加的函数的头文件

int main(){
	int sockfd = socket(AF_INET,SOCK_DGRAM,0);//网络通信AF_INET
	if (sockfd == -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("192.168.66.11");//点分十进制转十六进制
	int res = bind(sockfd,(struct sockaddr*)&addr,
			sizeof(addr));
	if (res == -1){
		perror("bind"),exit(-1);
	}
	printf("绑定成功\n");
	char buf[100] = {};
	res = read(sockfd,buf,100);
	printf("读到了%d字节,内容:%s\n",res,buf);
	close(sockfd);
	return 0;
}

client.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>

int main(){
	int sockfd = socket(AF_INET,SOCK_DGRAM,0);
	if (sockfd == -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("192.168.66.11");//都是服务器的,改成连接IP
	int res = connect(sockfd,(struct sockaddr*)&addr,
			sizeof(addr));
	if (res == -1){
		perror("connect"),exit(-1);
	}
	printf("连接成功\n");
	write(sockfd,"hello",5);
	close(sockfd);
}

抱歉!评论已关闭.