注意:开启程序的时候应该先开启server程序,再开启client程序。关闭程序的时候应该先关闭client程序,再关闭server程序。
/*****************************************服务器端************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#define SER_IP "127.0.0.1"
#define SER_PORT 6666
int main()
{
int lfd, cfd;
struct sockaddr_in serv_addr, clie_addr;
socklen_t clie_addr_len;
char buf[BUFSIZ], cline_IP[BUFSIZ];
int n = 0, i = 0, ret = 0;
printf("This is a server \n");
/*Step 1: 创建服务器端socket描述符lfd*/
lfd = socket(AF_INET, SOCK_STREAM, 0);
if(lfd == -1)
{
perror("socket error");
exit(1);
}
/*Step 2: bind绑定服务器端的IP和端口,固定下来后其他的所有客户端都向这个IP和端口发送和请求数据。客户端可以省略这一步*/
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(SER_PORT);
//serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); //INADDR_ANY是指定服务器中所有的可用的地址,凡是服务器中能用IP的对应端口收到的数据都会发到这个进程。
inet_pton(AF_INET, SER_IP, &serv_addr.sin_addr.s_addr); //inet_pton将SER_IP由点分十进制转为二进制整数。输出为&serv_addr.sin_addr
ret = bind(lfd, (struct sockaddr* )&serv_addr, sizeof(serv_addr));
if(ret == -1)
{
perror("bind error");
exit(2);
}
/*Step 3: listen确定服务器端最大保持连接的上限,这里为128*/
ret = listen(lfd, 128);
if(ret == -1)
{
perror("listen error");
exit(3);
}
/*Step 4: 服务器等待客户端的链接,返回值cfd为客户端的socket描述符。输出参数clie_addr为客户端的相关信息,参数clie_addr_len为输入输出参数*/
clie_addr_len = sizeof(clie_addr);
cfd = accept(lfd, (struct sockaddr* )&clie_addr, &clie_addr_len);
if(cfd == -1)
{
perror("accept error");
exit(4);
}
printf("登录的客户端的IP是:%s 端口号是:%d\n",
inet_ntop(AF_INET, &clie_addr.sin_addr.s_addr, cline_IP, sizeof(cline_IP)),
ntohs(clie_addr.sin_port));
#if 0
printf("开始接收数据3\n");
sleep(1);
printf("开始接收数据2\n");
sleep(1);
printf("开始接收数据1\n");
#endif
/*Step 5: 服务器从客户端socket描述符cfd中接收/读取数据,并向cfd中发送/写数据。*/
while(1)
{
n = read(cfd, buf, sizeof(buf));
for( i = 0; i < n; i++)
{
buf[i] = toupper(buf[i]);
}
n = write(cfd, buf, n);
}
/*Step 6: 关闭socket描述符*/
close(lfd);
close(cfd);
return 0;
}
/******************************************客户端************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#define SER_IP "127.0.0.1"
#define SER_PORT 6666
int main()
{
int lfd, cfd;
struct sockaddr_in serv_addr, clie_addr;
socklen_t clie_addr_len;
char buf[BUFSIZ];
int n = 0, i = 0, ret = 0 ;
printf("This is a client \n");
/*Step 1: 创建客户端端socket描述符cfd*/
cfd = socket(AF_INET, SOCK_STREAM, 0);
if(cfd == -1)
{
perror("socket error");
exit(1);
}
/*Step 2: 客户端可以不使用bind绑定客户端的IP和端口,操作系统会隐式帮它绑定*/
#if 0
ret = bind(cfd, (struct sockaddr* )&clie_addr, sizeof(clie_addr));
if(ret != 0)
{
perror("bind error");
exit(2);
}
#endif
/*Step 3: connect链接服务器端的IP和端口号*/
bzero(&serv_addr, sizeof(serv_addr));
//memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(SER_PORT);
inet_pton(AF_INET,SER_IP, &serv_addr.sin_addr.s_addr);
ret = connect(cfd,(struct sockaddr *)&serv_addr, sizeof(serv_addr));
if(ret != 0)
{
perror("connect error");
exit(3);
}
/*Step 4: 向服务器端写数据*/
while(1)
{
fgets(buf, sizeof(buf), stdin);
write(cfd, buf, strlen(buf));
n = read(cfd, buf, sizeof(buf));
write(STDOUT_FILENO, buf, n);//写到屏幕上
}
/*Step 5: 关闭socket描述符*/
close(cfd);
return 0;
}