一 、流程
二、网络字节序
uint32_t htonl(uint32_t hostlong) //本地字节序转网络字节序(IP) uint16_t htons(unit16_t hsoshort) //本地字节序转网络字节序(端口) uint32_t ntohl(unit32_t netlong) //网络字节序转本地字节序(端口) uint16_t ntohs(unit16_t netshort) //网络字节序转本地字节序(端口)
IP地址转换函数(常用的)
int inet_pton(int af, const char *src, void *dst)
把点分十进制的ip转换为网络字节序
af:当前的ip协议类型AF_INET AF_INET6
src:传入参数 IP地址(点分十进制)
dst:传出参数 转换后的网络字节序的IP地址
成功返回1 异常返回0(src指向的不是有效的IP地址) 失败返回-1
const char *inet_ntop(int af, const void *src,
char *dst, socklen_t size)
把网络字节序转换为本地字节序
af:AF_INET AF_INET6
src: 传入参数 网络字节序IP地址
dst:传出参数 本地字节序(string IP)
size:字节序的大小
三、函数API
1、
struct sockaddr
struct sockaddr_in {
sa_family_t sin_family;
in_port_t sin_port;
struct in_addr sin_addr;
};
struct in_addr {
uint32_t s_addr;
};
初始化的时候用下面的结构体初始化,传参的时候在强转为上面结构体的指针
成员初始化:
sin_family :AF_INET/AF_INET6(ipv4/ipv6)
sin_port:网络字节序的端口号
sin_addr.s_addr:(结构体嵌套结构体)网络字节序的IP地址 一般情况下赋值方法为
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
自动取当前系统中有效的IP地址。 默认整形,进行字节序转换
2、
int socket(int domain, int type, int protocol)
socket函数:创建一个套接字
domain:选用的IP地址协议 通常为AF_INET(IPV4)、AF_INET6(IPV6)。
type:创建套接字所选用的数据传输协议 SOCK_STREAM、SOCK_DGRAM
protocol:所选用的协议的代表协议,默认为0(根据前面的所选的类型自动确定)(TCP/UDP)
返回值:成功:新套接字所对应的文件描述符 。失败:返回-1。
3、
int bind(int sockfd, const struct sockaddr *addr,
socklen_t addrlen)
bind:给socket绑定地址结构(IP + 端口号)
sockfd:socket函数的返回值
addr:传入参数(struct sockaddr *)&addr (进行强转)
addrlen:sizeof(addr)地址结构的大小
返回值:成功:0 。 失败-1。
4、
int listen(int sockfd, int backlog)
listen:设置同时与服务器链接的上限数(同时进行三次握手的客户端数量)
sockfd:socket函数的返回值
backlog:同时连接的数值
5、
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
accept:阻塞等待客户端连接,成功返回一个与客户端链接的socket文件描述符(新的文件描述符)
sockfd:socked函数的返回值。
addr:传出参数。成功与服务器建立链接的客户端的地址结构(IP+PORT)。
addrlen:传入传出参数。入:addr的大小 。 出:客户端addr的实际大小。
clit_addr_len = sizeof(clit_addr);
传参的时候传&clit_addr_len。
返回值:返回能与服务器进行数据通信的socket对应的文件描述符。失败返回-1。
6、
int connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen)
connect:与服务器建立连接
sockfd:客户端scoket函数的返回值
addr:传入参数 服务器的地址结构
addrlen:服务器地址结构的大小。
返回值: 成功0 失败-1。
三、代码实现
实现功能:客户端输入小写字符,服务器将小写字母转换为大写字母返回给客户端并打印。
服务器端:
1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 9 #define SERV_PORT 9257 10 11 int main() 12 { 13 int lfd = 0; 14 int cfd = 0; 15 char buf[BUFSIZ], client_IP[1024]; 16 //定义结构体并初始化 17 struct sockaddr_in serv_addr, clit_addr; 18 socklen_t clit_addr_len; 19 serv_addr.sin_family = AF_INET; 20 serv_addr.sin_port = htons(SERV_PORT); 21 serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); 22 23 //创建socket 24 lfd = socket(AF_INET, SOCK_STREAM, 0); 25 if (lfd == -1){ 26 perror("socket error"); 27 exit(1); 28 } 29 30 //绑定 31 int ret = bind(lfd, (const struct sockaddr *)&serv_addr, sizeof(serv_addr)); 32 if (ret == -1){ 33 perror("bid error"); 34 exit(1); 35 } 36 37 ret = listen(lfd, 128); 38 if (ret == -1){ 39 perror("listen error"); 40 exit(1); 41 } 42 43 //阻塞监听客户端建立链接 返回新的文件描述符 44 clit_addr_len = sizeof(clit_addr); 45 cfd = accept(lfd, (struct sockaddr *)&clit_addr, &clit_addr_len); 46 if (cfd == -1){ 47 perror("accept error"); 48 exit(1); 49 } 50 printf("client ip:%s port:%dn", 51 inet_ntop(AF_INET, &clit_addr.sin_addr.s_addr, client_IP, sizeof(client_IP)), 52 ntohs(clit_addr.sin_port)); 53 54 //服务器工作:读文件 55 int i = 0; 56 while(1){ 57 ret = read(cfd, buf, sizeof(buf)); 58 write(STDOUT_FILENO, buf, ret); 59 for(i = 0; i < ret; i ++){ 60 buf[i] = toupper(buf[i]); //小写转大写 61 } 62 write(cfd, buf, ret); 63 } 64 65 close(cfd); 66 close(lfd); 67 return 0; 68 }
客户端:
1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 8 #define SERV_PORT 9257 9 10 int main() 11 { 12 int cfd; 13 int conter = 10; 14 char buf[BUFSIZ]; 15 16 struct sockaddr_in serv_addr; //服务器的地址结构 17 serv_addr.sin_family = AF_INET; 18 serv_addr.sin_port = htons(SERV_PORT); 19 inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr); 20 serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); 21 22 cfd = socket(AF_INET, SOCK_STREAM, 0); 23 if (cfd == -1){ 24 perror("socket error"); 25 exit(1); 26 } 27 28 int ret = connect(cfd, (const struct sockaddr *)&serv_addr, sizeof(serv_addr)); 29 if (ret != 0){ 30 perror("connect error"); 31 exit(1); 32 } 33 while(conter--){ 34 write(cfd, "hellon", 6); 35 ret = read(cfd, buf, sizeof(buf)); 36 write(STDOUT_FILENO, buf, ret); 37 sleep(1); 38 } 39 close(cfd); 40 return 0; 41 } 42
程序运行结果:



