头文件
sys/socket.h 函数和数据结构定义在这个头文件里面
netinet/in.h IP v4和IP v6相关协议族需要的信息
sys/un.h UNIX机器间通信的相关信息(不涉及)
arpa/inet.h 处理数字从操作系统字节序到网络字节序(大端小端转换)
netdb.h 映射服务到IP地址
socketAPI
socket() 创建socket
bind() 绑定socket到IP地址和端口
listen() 服务器监听客户端连接
connect() 客户端连接到服务器
accept() 应用程序接受完成3次握手的客户端连接
send() recv(), write() read() 机器间相互发送数据
close() 关闭socket
gethostbyname() gethostbyaddr() v4专有
select() poll() 处理多个连接的读、写和错误状态
getsockopt() 得到对应socket的选项值
setsockopt() 设置对应socket的选项值
server
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char** argv)
{
char hello[] = "hello world";
struct sockaddr_in sa;
int SocketFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (-1 == SocketFD)
{
perror("cannot create socket");
exit(EXIT_FAILURE); // 1
}
memset(&sa, 0, sizeof(sa)); //对c的习惯
sa.sin_family = AF_INET;
sa.sin_port = htons(2222); //h to ns 操作系统字节序转化成网络字节序
sa.sin_addr.s_addr = htonl(INADDR_ANY);
if (-1 == bind(SocketFD, (struct sockaddr*)&sa, sizeof(sa)))
{
perror("bind failed");
exit(EXIT_FAILURE);
}
if (-1 == listen(SocketFD, 10))
{
perror("accept failed\n");
close(SocketFD); //释放掉资源
exit(EXIT_FAILURE);
}
for (;;)
{
int ConnectFD = accept(SocketFD, NULL, NULL);
if (0 > ConnectFD)
{
perror("accept failed");
exit(EXIT_FAILURE);
}
int writeSize = 0;
size_t totalWrite = 0;
while (totalWrite < sizeof(hello))
{
writeSize = write(ConnectFD, hello + totalWrite, sizeof(hello) - totalWrite);
if (-1 == writeSize)
{
perror("write failed");
close(ConnectFD);
close(SocketFD);
exit(EXIT_FAILURE);
}
totalWrite += writeSize;
}
if (-1 == shutdown(ConnectFD, SHUT_RDWR))
{
perror("shutdown failed\n");
close(ConnectFD);
close(SocketFD);
exit(EXIT_FAILURE);
}
close(ConnectFD);
}
close(SocketFD);
return EXIT_SUCCESS;
}
client
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
struct sockaddr_in sa;
int res;
//tcp
int SocketFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
//资源不够
if (-1 == SocketFD)
{
perror("cannot create socket");
exit(EXIT_FAILURE);
}
//初始化sa
memset(&sa, 0, sizeof(sa));
//设置连接服务器的 ip和端口号
sa.sin_family = AF_INET;
//端口号2222, htons把操作系统的字节序,转化为网络的字节序
sa.sin_port = htons(2222);
//连接本地ip地址
res = inet_pton(AF_INET, "127.0.0.1", &sa.sin_addr);
//客户端,设置连接服务器
//失败,则释放资源
if (-1 == connect(SocketFD, (struct sockaddr*)&sa, sizeof(sa)))
{
perror("connect failed\n");
close(SocketFD);
exit(EXIT_FAILURE);
}
char buffer[512];
int totalRead = 0;
for (;;)
{
int readSize = 0;
readSize = read(SocketFD, buffer + totalRead, sizeof(buffer) - totalRead);
if (readSize == 0)
{
//read all
break;
}
else if (readSize == -1)
{
perror("read failed");
close(SocketFD);
exit(EXIT_FAILURE);
}
char buffer[512];
int totalRead = 0;
for (;;)
{
int readSize = 0;
readSize = read(SocketFD, buffer + totalRead, sizeof(buffer) - totalRead);
if (readSize == 0)
{
//read all
break;
}
else if (readSize == -1)
{
perror("read failed");
close(SocketFD);
exit(EXIT_FAILURE);
}
totalRead += readSize;
}
buffer[totalRead] = 0;
printf("get from server: %s\n", buffer);
/* perform read wirte operations ...*/
(void)shutdown(SocketFD, SHUT_RDWR);
close(SocketFD);
return EXIT_SUCCESS;
}
以下为详解