服务端:
1、socket()获得一个sockfd。注意第二个参数必须SOCK_STREAM.
2、准备通信地址(必须服务器的)
3、bind()绑定。(开放了端口,允许客户端连接)
4、监听客户端 listen()函数
5、等待客户端的连接 accept(),返回用于交互的socket描述符
6、使用第5步返回sockt描述符,进行读写通信。
7、关闭sockfd。
客户端:
客户端的代码与一对一的一样。注意第二个参数必须SOCK_STREAM.
TCP一对多模型,有两类描述符:
第一步的描述符不再参与信息交互,只是等待客户端的连接(accept),accept()在客户端连接上来后,会返回一个新的描述符,用于读写通信。
#include
#include
#include
#include
#include
#include
#include
int main(){
int sockfd = socket(AF_INET,SOCK_STREAM,0);
if (sockfd == -1){
perror("socket"),exit(-1);
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(2222);
addr.sin_addr.s_addr = inet_addr("192.168.66.11");
int res = bind(sockfd,(struct sockaddr*)&addr,
sizeof(addr));
if (res == -1){
perror("bind"),exit(-1);
}
printf("bind ok\n");
listen(sockfd,100);//监听
struct sockaddr_in client;
socklen_t len = sizeof(client);
int fd = accept(sockfd,(struct sockaddr*)&client,&len);
char *from = inet_ntoa(client.sin_addr);//十六进制转点分十进制
printf("%s连接成功\n",from);
char buf[100] = {};
res = read(fd,buf,sizeof(buf));
printf("接受了%d字节,内容:%s",res,buf);
write(fd,"welcome",7);
close(fd);
close(sockfd);
return 0;
}
#include
#include
#include
#include
#include
#include
#include
int main(){
int sockfd = socket(AF_INET,SOCK_STREAM,0);
if (sockfd == -1){
perror("socket"),exit(-1);
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(2222);//连接端口
addr.sin_addr.s_addr = inet_addr("192.168.66.11");//都是服务器的,改成连接IP
int res = connect(sockfd,(struct sockaddr*)&addr,
sizeof(addr));
if (res == -1){
perror("connect"),exit(-1);
}
printf("连接成功\n");
write(sockfd,"hello",5);
char buf[100] = {};
res = read(sockfd,buf,sizeof(buf));
printf("读到了%d字节,内容:%s\n",res,buf);
close(sockfd);
return 0;
}
上面的服务端还只是实现了一对一的通信,一对多通信加一个while循环即可。
1、在客户端加上输入功能,允许发送不同的信息,并且客户端和服务器端代码要支持多次输入和输出(读写上加循环),输入bye退出。客户端发送的内容改为输入,服务器发回给客户端的内容改成客户端的输入。
2、可以考虑在服务器端启动多进程fork(),支持多个客户端的并行。
server.c
#include
#include
#include
#include
#include
#include
#include
#include
int sockfd;
void fa(int signo){
printf("服务器正在关闭\n");
sleep(1);
close(sockfd);
exit(0);
}
int main(){
printf("ctrl+c退出服务器\n");
signal(SIGINT,fa);
int sockfd = socket(AF_INET,SOCK_STREAM,0);
if (sockfd == -1){
perror("socket"),exit(-1);
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(2222);
addr.sin_addr.s_addr = inet_addr("192.168.66.11");
int reuseaddr = 1;//解决地址已被占用问题
setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,
&reuseaddr,sizeof(reuseaddr));
int res = bind(sockfd,(struct sockaddr*)&addr,
sizeof(addr));
if (res == -1){
perror("bind"),exit(-1);
}
printf("bind ok\n");
listen(sockfd,100);//监听
while (1){
struct sockaddr_in client;
socklen_t len = sizeof(client);
int fd = accept(sockfd,(struct sockaddr*)&client,
&len);//阻塞函数
char *from = inet_ntoa(client.sin_addr);
printf("%s连接成功\n",from);
pid_t pid = fork();
if (pid == 0){
char buf[100] = {};
while (1){
res = read(fd,buf,sizeof(buf));
printf("接受了%d字节,内容:%s\n",res,buf);
if (res <= 0){//包括0和-1
break;
}
if (strcmp(buf,"bye") == 0){
break;
}
write(fd,buf,strlen(buf));
memset(buf,0,sizeof(buf));
}
close(fd);
exit(0);
}
close(fd);
}
}
client.c
#include
#include
#include
#include
#include
#include
#include
int main(){
int sockfd = socket(AF_INET,SOCK_STREAM,0);
if (sockfd == -1){
perror("socket"),exit(-1);
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(2222);//连接端口
addr.sin_addr.s_addr = inet_addr("192.168.66.11");//都是服务器的,改成连接IP
int res = connect(sockfd,(struct sockaddr*)&addr,sizeof(addr));
if (res == -1){
perror("connect"),exit(-1);
}
printf("连接成功\n");
char buf[100] = {};
while (1){
memset(buf,0,sizeof(buf));//buf清0
printf("请输入要说的话\n");
scanf("%s",buf);
write(sockfd,buf,strlen(buf));
if (strcmp(buf,"bye") == 0){//退出的合适位置
break;
}
memset(buf,0,sizeof(buf));//buf清0
res = read(sockfd,buf,sizeof(buf));
printf("读到了%d字节,内容:%s\n",res,buf);
}
close(sockfd);
return 0;
}