【网络编程】TCP网络编程
TCP网络程序设计
一、模型函数化
图片:TCP编程模型
1.1 创建套接字Socket
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
1.2 绑定地址 Bind
图片 地址类型Struct
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
//通用地址类型
struct sockaddr
{
sa_family_t sa_family;//协议族类型
char sa_data[14];//地址
}
// IPV4 地址类型
struct sockaddr_in
{
short int sin_family;
unsigned short int sin_port;//Port
struct in_addr sin_addr; //IP地址 4 bytes int (整数型IP地址)
unsigned char sin_zero[8];//填充???
}
struct in_addr
{
unsigned long s_addr;
}
1.3 地址转换(网络字节序——整数型)
- 函数inet_addr
in_addr_t inet_addr(const char *cp)
功能:将字符串形式的IP地址转化为整数型的IP地址(网络字节序)
范例: in_addr.saddr = inet_addr(“192.168.1.1” );
- 函数inet_ntoa
char *inet_ntoa (struct in_addr)
功能:将整数形式的IP地址转化为字符串形式的IP地址
1.4 设置Listen监听端口
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int listen(int sockfd, int backlog);
1.5 等待连接accept
//无客户机连接时,服务器阻塞
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
1.6 发送数据 send
#include <sys/types.h>
#include <sys/socket.h>
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
1.7 接收数据 recv
#include <sys/types.h>
#include <sys/socket.h>
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
1.8 关闭连接 close
1.9 连接服务器 connect
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
二、网络字节序
- 网络字节序 —— 大端模式
图片 网络字节序转换
网络字节序转换
//发送方
uint32_t htonl(uint32_t hostlong); //将32位的数据从主机字节序转换为网络字节序(host to)
in_addr.saddr = htonl(INADDR_ANY)
uint16_t htons(uint16_t hostshort); //将16位的数据从主机字节序转换为网络字节序
//接收方
uint32_t ntohl(uint32_t netlong); //将32位的数据从网络字节序转换为主机字节序
uint16_t ntohs(uint16_t netshort); //将16位的数据从网络字节序转换为主机字节序
htonl()ntohl()htons()函数的英语全称
htonl()--"Host to Network Long"
ntohl()--"Network to Host Long"
htons()--"Host to Network Short"
ntohs()--"Network to Host Short"
以上函数是为了解决大小端不一致导致数据传送错误的问题
吐槽:
如果给出了一些函数的全称其实很好理解,可惜国内许多翻译人还是作者不知道是严重高估了读者的英语水平还是刻意的,翻译或者编写的东西莫名奇妙.
两大重灾区:计算机书籍 编程语言书籍(特别特别是汇编语言)非得逼人读原著.
三、编程实例——TCP通讯程序设计
/* tcp_server.c */
#include <stdio.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#define portnum 2333
int main()
{
int sockfd;
int new_fd;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
char buffer[128];
int nbyte;
int sin_size;
//1.创建套接字
if(sockfd = socket(AF_INET,SOCK_STREAM,0) == -1)
{
printf("Creat socket error!\n");
exit(1);
}
//2.1设置要绑定的地址
bzero(&server_addr,sizeof(struct sockaddr_in));//清零
server_addr.sin_family = AF_INET;//IPV4 protocol
server_addr.sin_port = htons(portnum);//port,本地主机字节序——>网络字节序
server_addr.sin_addr.s_addr = htonl (INADDR_ANY);
//2.2绑定地址
bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr));
//3.监听端口
listen(sockfd,5);
while(1)
{
//4.等待连接
sin_size = sizeof(struct sockaddr);
new_fd = accept(sockfd,(struct sockaddr *)(&client_addr),&sin_size);
printf("Server get connection from %s\n",inet_ntoa(client_addr.sin_addr));
//5.接收数据
nbyte = recv(new_fd,buffer,128,0);//实际收到的数据字节长度
buffer[nbyte] = '\0';
printf("server received:%s\n",buffer );
//6.结束连接
close(new_fd);
}
close(sockfd);
return 0;
}
/* tcp_client.c */
#include <stdio.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#define portnum 2333
//#define ip_address "192.168.240.133"
int main()
{
int sockfd;
struct sockaddr_in server_addr;
char buffer[128];
//1.创建套接字
if(sockfd = socket(AF_INET,SOCK_STREAM,0) == -1)
{
printf("Creat socket error!\n");
exit(1);
}
//2.1设置要连接的服务器的地址
bzero(&server_addr,sizeof(struct sockaddr_in));//清零
server_addr.sin_family = AF_INET;//IPV4 protocol
server_addr.sin_port = htons(portnum);//port,本地主机字节序——>网络字节序
server_addr.sin_addr.s_addr = inet_addr("192.168.240.133");
//2.连接服务器
if(connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr)) == -1)
{
printf("connect error!\n");
exit(1);
}
//3.发送数据到服务器
printf("please input :\n");
fgets(buffer,128,stdin);
send(sockfd,buffer,strlen(buffer),0);
//4.关闭连接
close(sockfd);
return 0;
}