socket客户/服务器模型
用到的函数
socket函数
流式套接字就是TCP,数据包套接字就是UDP
一个程序最多打开一般来说是1024个文件描述符,由一个系统的参数来确定的,叫open files。
bind函数
listen函数
accept函数
在完成连接队列为空时,accept会阻塞
- 第二个和第三个参数,要么都是空指针,要么都不是空指针
connect函数
read函数
write函数
例子
客户端编程
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
int main(){
int sock;
if(sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) < 0)//其实前两个已经表示为是tcp协议了,第三个参数可以填0
{
ERR_EXIT("socket");//报错误的宏
}
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));//全部填充0
servaddr.sin_family = AF_INET;
servaddr.sin_prot = htons(5188);
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
if(connect(sock, (struct sockaddr*)servaddr, sizeof(servaddr)) < 0){
ERR_EXIT("connect");
}
char recvbuf[1024] = {0};
char sendbuf[1024] = {0};
while(fgets(sendbuf, sizeof(sendbuf), stdin)!= NULL){
write(sock, sendbuf, strlen(sendbuf));
read(sock, recvbuf, sizeof(recvbuf));
fputs(recvbuf, stdout);
memset(sendbuf, 0, sizeof(sendbuf));//清空缓存区
memset(recvbuf, 0, sizeof(recvbuf));
}
close(sock);
return 0;
}
服务器编程
监听套接字:listenfd
已连接套接字:conn
注意这里listen之后,客户端就已经能够搜索到了
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
int main(){
int listenfd;
if(listenfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) < 0)//其实前两个已经表示为是tcp协议了,第三个参数可以填0
{
ERR_EXIT("socket");//报错误的宏
}
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));//全部填充0
servaddr.sin_family = AF_INET;
servaddr.sin_prot = htons(5188);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//参数表示本机的任意地址,以下两种也是正确的写法
//servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
//inet_aton("127.0.0.1", &servaddr.sin_addr);
if(bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0){//一旦绑定完成,这个套接字就会被认为是被动套接字,否则是主动套接字。
ERR_EXIT("bind");
}
if(listen(listenfd, SOMAXCONN) < 0)//后面的宏,代表队列的最大值
{
ERR_EXIT("listen");
}
struct sockaddr_in peeraddr;
socklen_t peerlen = sizeof(peeraddr);
int conn;
if((conn = accept(listenfd, (struct sockaddr*)&peeraddr, &peerlen)) < 0){//这里返回值是文件描述符
ERR_EXIT("accept");
}
char recvbuf[1024];
while(1){
memset(recvbuf, 0, sizeof(recvbuf));
int ret = read(conn, recvbuf, sizeof(recvbuf));
fputs(recvbuf, stdout);
write(conn, recvbuf, ret);
}
close(conn);
close(listenfd);
return 0;
}