一、什么是网络
网络是一组计算机或网络设备通过有形的线缆或无形的媒介如无线,连接起来,按照一定的规则,进行通信的集合。
二、TCP/IP模型
1.应用层:HTTP(万维网服务),FTP(文件传输),SMTP(电子邮件),SSH(安全远程登陆),DNS(名称<-> IP地址寻找,域名系统)
2.传输层:TCP(面向字节流), UDP(面向报文)
3.网络层:IP协议就在这里,它负责对数据加上IP地址和其他的数据以确定传输的目标。
4.网络接口层(数据链路层):这个层次为待传送的数据加入一个以太网协议头,并进行CRC编码,为最后的数据传输做准备。
三、四元组
源和目标 IP地址(来自网络层)源和目标端口号标识
网络层的“ip地址”可以唯一标识网络中的主机,而传输层的“协议+端口”可以唯一标识主机中的应用程序(进程)。就可以标识网络的进程了,网络中的进程通信就可以利用这个标志与其它进程进行交互。
四、TCP三次握手示意图
五、TCP流程图
六、常用API函数
int socket(int domain, int type, int protocol); //新建一个socket端口
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);// 绑定socket端口
int listen(int sockfd, int backlog);//建立监听
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);//进入等待客户端连接模式,并阻塞当前进程/线程
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);//客户端连接到服务器ssize_t send(int sockfd, const void *buf, size_t len, int flags); //通过已建立到通信socket发送数据,类似于函数
writessize_t recv(int sockfd, void *buf, size_t len, int flags);//接收另一端通过socket发送的数据
//网络通信相关辅助函数如下
//主机字节序/网络字节序端口号 互转
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
//IP 地址转换
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int inet_aton(const char *cp, struct in_addr *inp);
七、示例程序
客户端:
int sock_fd;
struct sockaddr_in server_addr;
int ret;
char send_buf[1000];
socklen_t send_len;
if (argc != 2)
{
fprintf(stderr, "Usage:%s hostname\n\a", argv[0]);
exit(1);
}
/* socket */
sock_fd = socket(AF_INET, SOCK_STREAM, 0);//AF_INET:IPV4;SOCK_STREAM:TCP
if (-1 == sock_fd)
{
fprintf(stderr, "socket error:%s\n", strerror(errno));
exit(1);
}
/* set sockaddr_in parameter*/
memset(&server_addr, 0, sizeof(struct sockaddr_in));//clear
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT_NUMBER);
ret = inet_aton(argv[1], &server_addr.sin_addr); //将一个字符串IP地址转换为一个32位的网络序列IP地址
if (0 == ret)
{
fprintf(stderr, "server_ip error.\n");
close(sock_fd);
exit(1);
}
/* connect */
ret = connect(sock_fd, (const struct sockaddr*)&server_addr, sizeof(struct sockaddr));
if (-1 == ret)
{
fprintf(stderr, "connect error:%s\n", strerror(errno));
close(sock_fd);
exit(1);
}
while (1)
{
if (fgets(send_buf, 999, stdin))
{
/* send */
send_len = send(sock_fd, send_buf, strlen(send_buf), 0);
if (send_len <= 0)
{
fprintf(stderr, "send error:%s\n", strerror(errno));
close(sock_fd);
exit(1);
}
}
}
/* close */
close(sock_fd);
服务器:
int sock_fd, new_fd;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
int ret;
socklen_t addr_len;
int recv_len;
unsigned char recv_buf[1000];
int client_num = -1;
signal(SIGCHLD, SIG_IGN); //在一个进程终止或者停止时,将SIGCHLD信号发送给其父进程。按系统默认将忽略此信号。如果 父进程希望被告知其子系统的这种状态,则应捕捉此信号。信号的捕捉函数中通常调用wait函数以取得进程ID和其终止状态。这个符号表示忽略该信号,执行了相应的signal()调用后,进程会忽略类型为sig的信号
/* socket */
sock_fd = socket(AF_INET, SOCK_STREAM, 0);//AF_INET:IPV4;SOCK_STREAM:TCP
if (-1 == sock_fd)
{
fprintf(stderr, "socket error:%s\n\a", strerror(errno));
exit(1);
}
/* set server sockaddr_in */
memset(&server_addr, 0, sizeof(struct sockaddr_in));//clear
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);//INADDR_ANY:This machine all IP
server_addr.sin_port = htons(PORT_NUMBER);
/* bind */
ret = bind(sock_fd, (struct sockaddr*)(&server_addr), sizeof(struct sockaddr));
if (-1 == ret)
{
fprintf(stderr, "bind error:%s\n\a", strerror(errno));
close(sock_fd);
exit(1);
}
/* listen */
ret = listen(sock_fd, BACKLOG);
if (-1 == ret)
{
fprintf(stderr, "listen error:%s\n\a", strerror(errno));
close(sock_fd);
exit(1);
}
/* accept */
while (1)
{
addr_len = sizeof(struct sockaddr);
new_fd = accept(sock_fd, (struct sockaddr*)&client_addr, &addr_len);
if (-1 == new_fd)
{
fprintf(stderr, "accept error:%s\n\a", strerror(errno));
close(sock_fd);
exit(1);
}
client_num++;
fprintf(stderr, "Server get connetion form client%d: %s\n", client_num, inet_ntoa(client_addr.sin_addr));//将一个字符串IP地址转换为一个32位的网络序列IP地址
if (!fork())
{
/* Child process */
while (1)
{
/* recv */
recv_len = recv(new_fd, recv_buf, 999, 0);
if (recv_len <= 0)
{
fprintf(stderr, "recv error:%s\n\a", strerror(errno));
close(new_fd);
exit(1);
}
else
{
recv_buf[recv_len] = '\0';
printf("Get msg from client%d: %s\n", client_num, recv_buf);
}
}
close(new_fd);
}
}
/* close */
close(sock_fd);
exit(0);
评论(0)
您还未登录,请登录后发表或查看评论