网络编程 回声服务器
服务器端
#include<sys/types.h>
#include<sys/socket.h>
#include<iostream>
#include<netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
#include<unistd.h>
using namespace std;
#define duankou 999
int main2() {
int box;
box = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in label;
bzero(&label, sizeof(label));
label.sin_family = AF_INET;
label.sin_addr.s_addr = htonl(INADDR_ANY);
label.sin_port = htons(duankou);
//函数说明htons()用来将参数指定的16位
//hostshort转换成网络字符顺序。返回值
//返回对应的网络字符顺序
bind(box, (struct sockaddr*)&label, sizeof(label));//
listen(box, 65);
cout << "wait .........." << endl;
while (1) {
struct sockaddr_in kehu;//客服端的结构体
int b;
socklen_t a; // 实际上是int 历史原因造成
a=sizeof(kehu);
b=accept(box, (struct sockaddr*)&kehu, &a);
// 这里也给客户端的机构体赋值
char addr[64];
cout << "客户端 ip" <<
inet_ntop(AF_INET, &kehu.sin_addr.s_addr, addr, sizeof(addr))<<endl;
//将网络字节序转换成 主机字节序的字符串
cout << "客户端的端口号" << ntohs(kehu.sin_port) << endl;
//函数说明
//ntohs()用来将参数指定的16位netshort转换成主机字符顺序。
//返回值返回对应的主机顺序。
char buff[250]; int lenth;
lenth=read(b, buff, (sizeof(buff)) - 1); // 读取客户端发送的数据
buff[lenth] = '\0';
cout << buff << endl;
int lenth_2;
lenth_2=write(b, buff, lenth);// 写入客户端
close(b);
}
}
socket
socket 返回值是一个整数 文件句柄 可以通过这个文件句柄读写
网络字节序
主机字节序: 一般都是小端字节序
网络字节序 一般都是大端格式
#include<arpa/inet.h>
unit32_t htonl(unit32_t hostlong) 把主机转换成网络 32位 ip 整数
unit16_t htons(unit16_t hostlong) 把主机转换成网络 16位 端口 整数
unit32_t ntohl(unit32_t netlong) 把网络转换成主机 32位 ip 整数
unit16_t ntohs(unit16_t netshort) 把网络转换成主机 16位 端口 整数
sockaddr_in 结构体 后面出现 针对于 ipv4 使用时 转化成 sockaddr *
sin_family 选择协议家族 AF_INET (ipv4)
sin_addr.s_addr 保存ip地址
sin_port 保存端口号
ip地址转化函数
inet_pton( ) 把ip字符串转化成大端格式的网络字节序的ip
inet_ntop( ) 把网络字节序转化成ip的字符串
inet_ntop(AF_INET,&sin_addr.s_addr,保存的字符串,字符串的大小 );
int main(void) {
const char a[]= "1.2.3.4";// 小端格式 主机字节序
struct sockaddr_in xx;
inet_pton(AF_INET, a,&xx.sin_addr.s_addr);//转换成大端格式
//这里保存的是整数 xx.sin_addr.s_addr;
printf("%x\n",xx.sin_addr.s_addr);
// 保存的是大端格式 网络字节序
printf("%d\n",ntohl(xx.sin_addr.s_addr));
// 小端格式 主机字节序
socket 函数
socket 的头文件 #include<sys/types.h> #include<sys/socket.h>
int socket(int domain,int type,int protocol); 也就是向系统注册,通知系统建立一通信端口
返回值
成功则返回socket处理代码,失败返回-1。
domain(域名)
参数domain 指定使用何种的地址类型, AF_INET Ipv4网络协议
AF_INET6 ipv6 网络协议
AF_UNIX 本地协议
type
SOCK_STREAM 提供双向连续且可信赖的数据流,即TCP协议
protocol
用来指定socket所使用的传输协议编号,通常此参考不用管它,设为0即可。
bind 函数
int bind(int sockfd,const struct sockaddr*addr, socklen_t addrlen)
将socket文件句柄和 ip地址和端口号进行绑定
int sockfd socket 文件句柄
sockaddr*addr ip地址和端口号的结构体的地址
socklen_t addrlen 结构体的长度
listen 函数
int listen(int s,int backlog);
listen()用来等待参数s 的socket连线。
参数backlog指定同时能处理的最大连接要求
返回值
成功则返回0,失败返回-1,错误原因存于errno
accept函数
int accept(int s,struct sockaddr * addr,int * addrlen);
s的socket连线 参数s的socket必需先经bind()、listen()函数处理过
参数addr所指的结构会被系统填入远程主机的地址数据
参数addrlen为scokaddr的结构长度
返回值
成功则返回新的socket处理代码,失败返回-1,错误原因存于errno中。
connect 函数
定义函数
int connect (int sockfd,struct sockaddr * serv_addr,int addrlen);
函数说明
sockfd 客服端的文件句柄
serv_addr 客服器的ip和端口号的结构体
addrlen 结构体的长度
成功则返回0,失败返回-1,错误原因存于errno中。