1、Linux的优点之一就是在于它丰富而稳定的网络协议栈。
2.TCP/IP协议族体系结构
3.数据封装
应用程序数据在发送到屋里网络上之前,将沿着协议栈从上往下依次传递。每层协议都将在上层协议的基础上加上自己的头部信息(有时还包括尾部信息),以实现该层的功能,这个过程称为封装。
4、IP协议
1.、IP包由IP协议头与协议数据两部分构成。
5、TCP协议
1、TCP协议头部结构
6、UDP协议
1、UDP协议头部结构
7、Socket
Linux中的网络编程通过Socket(套接字)接口实现,Socket是一种文件描述符。
套接字socket有三种类型:1.流式套接字,2.数据报套接字,3.原始套接字
struct sockaddr_in { short int sin_family; /* Internet地址族 */
unsigned short int sin_port; /* 端口号 */
struct in_addr sin_addr; /* IP地址 */
unsigned char sin_zero[8]; /* 填0 */ };
编程中一般并不直接针对sockaddr数据结构操作,而是使用与sockaddr等价的sockaddr_in数据结构。
8、进行Socket编程的常用函数有:
socket:创建一个socket
bind:用于绑定IP地址和端口号到socket
connect:该函数用于绑定之后的client端与服务器建立连接
listen:设置能处理的最大连接要求,Listen()并未开始接收连线,只是设置socket为listen模式
accept:用来接受socket连接
send :发送数据
recv:接收数据
TCP服务器:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <pthread.h>
#define PORT 8000
#define SIZE 1000
void *ClientHandler(void *arg)
{
int ret;
char buf[32] = {0};
int fd = *(int *)arg;
pthread_detach(pthread_self());
while (1)
{
ret = recv(fd, buf, sizeof(buf), 0);
if (-1 == ret)
{
perror("recv");
exit(1);
}
if (!strcmp(buf, "bye"))
{
close(fd);
break;
}
printf("recv from %d client %s\n", fd, buf);
memset(buf, 0, sizeof(buf));
}
}
int main()
{
int sockfd;
int ret, fd[SIZE], i = 0;
pthread_t tid;
struct sockaddr_in server_addr; //用于保存服务器信息
struct sockaddr_in client_addr; //用于保存客户端信息
sockfd = socket(PF_INET, SOCK_STREAM, 0);
if (-1 == sockfd)
{
perror("socket");
exit(1);
}
//保存服务器信息
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = PF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
ret = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (ret < 0)
{
perror("bind");
exit(1);
}
ret = listen(sockfd, 5);
if (ret < 0)
{
perror("listen");
exit(1);
}
int length = sizeof(client_addr);
char buf[32] = {0};
while (1)
{
printf("waitting for connect...\n");
fd[i] = accept(sockfd, (struct sockaddr *)&client_addr, &length); //接受连接
if (-1 == fd[i])
{
perror("accept");
exit(1);
}
printf("client connect success port : %d fd : %d\n", client_addr.sin_port, fd[i]);
ret = pthread_create(&tid, NULL, ClientHandler, &fd[i]);
if (ret != 0)
{
perror("pthread_create");
}
i++;
}
close(sockfd);
return 0;
}
TCP客户端:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#define PORT 8000
int sockfd;
void StopClient(int num) //进程收到SIGINT信号,退出
{
send(sockfd, "bye", strlen("bye"), 0);
close(sockfd);
printf("BYE!\n");
exit(1);
}
int main()
{
int ret;
struct sockaddr_in server_addr;
signal(SIGINT, StopClient);
sockfd = socket(PF_INET, SOCK_STREAM, 0);
if (-1 == sockfd)
{
perror("socket");
exit(1);
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = PF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
ret = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (-1 == ret)
{
perror("connect");
exit(1);
}
char buf[32] = "helloworld";
while (1)
{
ret = send(sockfd, buf, strlen(buf), 0);
if (-1 == ret)
{
perror("send");
exit(1);
}
sleep(1);
}
return 0;
}
UDP服务器:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 8888
int main()
{
int sockfd, ret;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
sockfd = socket(PF_INET, SOCK_DGRAM, 0);
if (-1 == sockfd)
{
perror("socket");
exit(1);
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = PF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = inet_addr("192.168.1.10");
ret = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (ret < 0)
{
perror("bind");
exit(1);
}
char buf[32] = {0};
int length = sizeof(client_addr);
while (1)
{
ret = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&client_addr,
(socklen_t *)&length);
if (ret < 0)
{
perror("recvfrom");
}
printf("recv from %d %s\n", client_addr.sin_port, buf);
memset(buf, 0, sizeof(buf));
}
return 0;
}
UDP客户端:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define PORT 8888
int main(int argc, char *argv[])
{
int sockfd, ret;
struct sockaddr_in server_addr;
sockfd = socket(PF_INET, SOCK_DGRAM, 0);
if (-1 == sockfd)
{
perror("socket");
exit(1);
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = PF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = inet_addr("192.168.1.10");
char buf[32] = {0};
int length = sizeof(server_addr);
int fd = open(argv[1], O_RDONLY);
if (-1 == fd)
{
perror("open");
exit()
}
while (1)
{
scanf("%s", buf);
ret = sendto(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&server_addr, length);
if (ret < 0)
{
perror("sendto");
}
memset(buf, 0, sizeof(buf));
}
return 0;