基于TCP协议的回显服务器,简单的只有一个连接客户端。
服务器流程:
1.创建文件描述符sock,并初始化 sockaddr_in ip地址和端口号
2.bind() 绑定文件描述符
3.accept() 阻塞等待客户端连接,返回新的文件描述符 newsock
4.循环读写客户端请求和响应
server.c
#include
#include
#include
#include
#include
#include
#include
#include
//./server 0 8080
int main(int argc,char *argv[])
{
if(argc != 3)
{
printf("usage: ./client [ip] [port]");
return 1;
}
//创建文件描述符
int sock = socket(AF_INET,SOCK_STREAM,0);
if(sock < 0)
{
printf("create socket error\n");
return 2;
}
struct sockaddr_in server_socket;
server_socket.sin_family = AF_INET;
server_socket.sin_port = htons(atoi(argv[2]));
server_socket.sin_addr.s_addr = inet_addr(argv[1]);
//绑定文件描述符,IP/PORT
if(bind(sock,(struct sockaddr*)&server_socket,sizeof(struct sockaddr_in))<0)
{
printf("bind error\n");
return 3;
}
printf("bind and listen success..\n");
struct sockaddr_in peer;
char buf[1024];
while(1)
{
//调用accept函数,阻塞等待客户端连接,返回值是新的newsock
socklen_t len = sizeof(peer);
int new_sock = accept(sock,(struct sockaddr*)&peer,&len) ;
if(new_sock < 0)
{
printf("accept error\n");
return 5;
}
//循环读写客户端得请求
while(1)
{
memset(buf,'\0',sizeof(buf));
if(read(new_sock,buf,sizeof(buf)) < 0)
{
printf("read error\n");
return 6;
}
printf("cient # %s\n",buf);
if(write(new_sock,buf,sizeof(buf))<0)
{
printf("write error\n");
return 7;
}
}
}
//记得关闭文件描述符
close(sock);
return 0;
}
客户顿简单流程:
1.创建文件描述符sock
2.调用connect()函数,请求连接服务器
3.连接成功,循环请求
client.c
#include
#include
#include
#include
#include
#include
#include
#include
// ./client 127.0.0.1 8080
int main(int argc,char *argv[])
{
if(argc != 3)
{
printf("usage: ./client [ip] [port]");
return 1;
}
//创建文件描述符sock
int sock = socket(AF_INET,SOCK_STREAM,0);
if(sock < 0)
{
printf("create socket error\n");
return 2;
}
struct sockaddr_in client_socket;
client_socket.sin_family = AF_INET;
client_socket.sin_port = htons(atoi(argv[2]));
client_socket.sin_addr.s_addr = inet_addr(argv[1]);
//调用connect() 函数 请求和服务器连接(三次握手)
int ret = connect(sock,(struct sockaddr*)&client_socket,sizeof(client_socket));
if(ret < 0)
{
printf("connect failed...\n");
return 3;
}
printf("connect success..\n");
char buf[1024];
memset(buf,'\0',sizeof(buf));
//循环请求服务器,服务器响应
while(1)
{
printf("client:#");
fgets(buf,sizeof(buf),stdin);
socklen_t len = strlen(buf);
buf[len-1] = '\0';
write(sock,buf,sizeof(buf));
printf("pleas wait...\n");
read(sock,buf,sizeof(buf));
printf("server # : %s\n",buf);
}
close(sock);
return 0;
}
使用指令 netstat -nltp 指令来查看现在系统中有多少的基于TCP协议上的通信:
上面的代码完成了我们想要的回显功能,客户端和服务器完成了数据交互。
当我们再启动另一个客户端时,再连接服务器,发现连接上了,但是却无法完成数据交互。
服务器没有响应。
看我们的代码可以看到,我们调用accept后,程序就一直在read阻塞等待了,并不能再accept另一个文件描述符了。
我们可以怎么处理这个问题呢。多进程,多线程可以解决。