一、 预备知识
1 、socket
1 是网络编程的一个编程接口,是一个特殊的文件描述符
并不仅限于tcp/ip,也可用于本机通讯
2 流式套接字TCP ,数据报套接字 UDP,原始套接字可直接操作网络层发送数据
3 套接口位于应用层和传输层直接
2、 IP地址
192.168.1.123 ->可以转换为32为无符号正数,每一组数字代表一个字节
分为 A B C D四类,D类为组播地址
子网掩码 255.255.255.0
192.168.1.123 & 255.255.255.0 = 192.168.1.0 网络地址
inet_addr() 192.168.1.123 转换成32位无符号正数
inet_ntoa() 32位无符号正数转换成192.168.1.123
3 、端口号
通过协议和端口号可以确定传输层的数据交给那个进程处理
TCP端口号和UDP端口号独立
4、 网络字节序
网络字节序 大端
大端存储数据低字节存高位,高字节存低位数据
小端存储数据低字节存低位。高字节存高位
字节序转换函数,h:host, n:net, l:u_long, s:u_short
htonl ,htons, ntohl, ntohs
二、 系统调用
1 、socket
int socket (int domain, int type, int protocol);
domain:地址族 AF_INET ipv4
type:指定套接口类型
protocol:通常设置为0
返回值:socket描述符
2 、int bind(int sockfd, struct sockaddr *my_addr, int addrlen) ;
将socket绑定端口和地址,sockaddr是一个通用地址结构
注意sa_data字符数组用来保存地址和端口数据
struct sockaddr
{
u_short sa_family; // 地址族, AF_xxx
char sa_data[14]; // 14字节协议地址
};
通常使用sockaddr_in来设置地址和端口,然后转换成sockadd类型指针使用
struct sockaddr_in struct sockaddr_un
{
u_short sin_family; // 地址族, AF_INET,2 bytes
u_short sin_port; // 端口,2 bytes
struct in_addr sin_addr; // IPV4地址,4 bytes
char sin_zero[8]; // 8 bytes unused,作为填充
};
3 、int listen (int sockfd, int backlog)
指定正在等待队列的长度
4、 int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) ;
接受一个客户端连接,返回值为已经建立好的socket描述符
sockfd:监听套接字
addr:accept后又accept填充此结构体,可以通过sockaddr_in获取对方IP和端口
addrlen:sockaddr长度
5、 int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
sockfd: 客户端socket
serv_addr: 服务端接口和地址
addrlen :sockaddr结构体长度
6 、ssize_t send(int socket, const void *buffer, size_t length, int flags)
socket:发送数据的socket
buffer:发送数据buf
length:发送数据长度
flags:通常为0
7 、ssize_t recv(int socket, const void *buffer, size_t length, int flags)
socket:接受数据的socket
buffer:保存数据buf
lenght:保存数据的buf大小
flags:通常为0
server.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define BUF_SIZE 100
int main()
{
//create socket
int iServer = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == iServer)
{
return -1;
}
printf("create socket ok\r\n");
//bind
struct sockaddr_in stServer;
memset(&stServer, 0, sizeof(struct sockaddr_in));
stServer.sin_family = AF_INET;
stServer.sin_port = htons(8888);
//stServer.sin_addr.s_addr = inet_addr("0.0.0.0");
stServer.sin_addr.s_addr = INADDR_ANY;
int iRet = bind(iServer, (struct sockaddr *)&stServer, sizeof(struct sockaddr_in));
if (-1 == iRet)
{
return -1;
}
printf("bind ok\r\n");
//listen
iRet = listen(iServer, 5);
if (-1 == iRet)
{
return -1;
}
printf("listen ok\r\n");
//accept
struct sockaddr_in stClient;
socklen_t tLen = sizeof(struct sockaddr_in);
char buf[BUF_SIZE];
while(1)
{
memset(&stClient, 0, sizeof(struct sockaddr_in));
memset(buf, 0, BUF_SIZE);
int iClient = accept(iServer, (struct sockaddr *)&stClient, &tLen);
if (iClient < 0)
{
continue;
}
printf("accept ok %d\r\n", iClient);
//recv send
iRet = recv(iClient, buf, BUF_SIZE, 0);
printf("recv %d\r\n", iRet);
if (iRet > 0)
{
printf("%s\r\n", buf);
send(iClient, buf, BUF_SIZE, 0);
}
close(iClient);
}
//close
close(iServer);
return 0;
}
client.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define BUF_SIZE 100
int main()
{
//create socket
int iClient = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == iClient)
{
return -1;
}
printf("socket ok\r\n");
//connect
struct sockaddr_in stServer;
memset(&stServer, 0, sizeof(struct sockaddr_in));
stServer.sin_family = AF_INET;
stServer.sin_port = htons(8888);
stServer.sin_addr.s_addr = inet_addr("127.0.0.1");
int iRet = connect(iClient, (struct sockaddr *)&stServer, sizeof(struct sockaddr));
if (-1 == iRet)
{
perror("connect");
return -1;
}
printf("connect ok\r\n");
//send
char buf[BUF_SIZE] = {0};
strcpy(buf, "hehexixi");
send(iClient, buf, BUF_SIZE, 0);
memset(buf, 0, BUF_SIZE);
//recv
iRet = recv(iClient, buf, BUF_SIZE, 0);
printf("%d %s\r\n", iRet, buf);
return 0;
}