服务器:
1 创建套接字---->socket
2 绑定服务器地址--->bind(设置服务器地址struct sockaddr_in)
3 监听---->listen
4 接受---->accept
5 通信---->read/write
客户端:
1 创建套接字---->socket
2 链接--->connect
5 通信---->read/write
服务器
1 创建套接字---->socket
函数原型 // int socket(int domain, int type, int protocol);
domain // AF_INET:使用ipv4协议来实现远程通讯
type // SOCK_STREAM:使用可靠传输
protocol // 0:使用选择传输的默认协议(SOCK_STREAM-->tcp)
int sockFD = socket(AF_INET,SOCK_STREAM,0);
2 绑定服务器地址--->bind(设置服务器地址struct sockaddr_in)
函数原型 // int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
sockfd // 为 1 中生成的sockFD
struct sockaddr{
sa_family_t sa_family;
char sa_data[14];
};
sturct sockaddr_in{
short sin_family;//协议
unsigned short sin_port;//端口号
struct in_addr sin_addr;//ip地址
unsigned char sin_zero[8];//为了填空
};
typedef unit_32t in_addr_t;
struct in_addr{
in_addr_t s_addr;
};
用 结构体 sockaddr_in 代替 aockaddr ,将数据传入 sockaddr_in。
struct sockaddr_in serAddr;
serAddr.sin_family = AF_INET; //使用ipv4协议通讯
htons:将本地字节序转换成网络字节序 host to network short
serAddr.sin_port = htons(6666);
inet_addr:将点分十进制字符串表示的ip转换成整数
serAddr.sin_addr.s_addr = inet_addr("192.168.137.128");
另外一种设置ip地址的方法
函数原型 int inet_pton(int af, const char *src, void *dst);
inet_pton(AF_INET, "192.168.1.37", &sin.sin_addr.s_addr);
将sockfd和指定的ip,port绑定,这样我们就可以通过sockfd收发该ip,port上的数据
bind(sockFD,(struct sockaddr*)&serAddr,sizeof(serAddr))
注意这里要将 sockaddr_in* 强转为 sockaddr*
3 监听---->listen
函数原型 // int listen(int sockfd, int backlog);
listen(serSockFD,20);
将sockfd设置为监听状态
20:表示客户端连接缓冲队列的大小
4 接受---->accept
函数原型 // int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
accept的参数在之前 2 中都已经详细介绍过了。
struct sockaddr_in cliAddr;
int newSockFD = -1;
int iAddrLen = sizeof(cliAddr);
newSockFD = accept(serSockFD,(struct sockaddr*)&cliAddr,&iAddrLen);
若没有客户端连接,则阻塞等待,接收从sockfd监听到的客户端会自动的将连接过来的客户端的ip,port等信息放入clientAddr中。函数成功会自动创建一个socket,专门用于服务器和该客户端数据交互。
5 通信---->read/write
一般将读写将给子进程处理
pthread_t threadForClient;
pthread_create(&threadForClient,NULL,handleClient,(void*)newSockFD);
子进程处理函数
void *handleClient(void *arg)
{
int sockFD = (int)arg;
write(sockfd, (char*)sendpdu, sendsize);
read(sockfd, (char*)revpdu, revsize);
}
客户端
客户端的操作和服务器基本一致,下面是客户端代码:
//1 创建套接字
int socket(int domain, int type, int protocol);
int ser_fd = socket(AF_INET, SOCK_STREAM, 0); //tcp
if(ser_fd < 0){
return -1;
}
//设置服务器地址
struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET; //设置协议族
sin.sin_port = htons(5555); //设置端口号(大端字节序)
//设置ip地址
int inet_pton(int af, const char *src, void *dst);
if(inet_pton(AF_INET, "192.168.1.37", &sin.sin_addr.s_addr) < 0){
return -1;
}
//2 链接服务器
int connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
if(connect(ser_fd, (const struct sockaddr*)&sin, sizeof(sin)) < 0){
return -1;
}
//数据传输
while(True){
//write/read
char buff[128] = {0};
printf("请输入一个字符串: ");
scanf("%s", buff);
//写向服务器
ssize_t write(int fd, const void *buf, size_t count);
write(ser_fd, buff, sizeof(buff));
}