朱有鹏 socket实际编程3(7)
(1)客户端和服务器原则上都可以任意的发和收,但是实际上双方必须配合:client发的时候server就收,而server发的时候client就收
(2)必须了解到的一点:client和server之间的通信是异步的,这就是问题的根源
(3)解决方案:依靠应用层协议来解决。说白了就是我们server和client事先做好一系列的通信约定
一、自定义应用层协议第一步:规定发送和接受方法
(1)规定连接建立后由客户端主动向服务器发出1个请求数据包,然后服务器收到数据包回复客户端一个回应数据包,这就是一个通信回合
(2)整个连接的通信就是由N多个回合组成的。
二、自定义应用层协议第二步:定义数据包格式
三、常用应用层协议:http、ftp。。。
四、UDP简介
server.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#define MYPORT 9003
#define SERADDR "192.168.30.128" //ifconfig看到的
#define BACKLOG 100 //允许排队100个
char recvbuf[100];
int main(void)
{
//第1步:先socket打开文件描述符
int sockfd = -1, ret = -1, clifd = -1;
socklen_t len = 0;
struct sockaddr_in seraddr = {0};//服务器的地址
struct sockaddr_in cliaddr = {0};//服务器的地址
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == sockfd)
{
perror("socket");
return -1;
}
printf("socketfd = %d.\n", sockfd);
//第2步:bind绑定socketfd和当前电脑的ip地址&端口号
seraddr.sin_family = AF_INET;//设置地址族为IPv4
//网络字节序是大端模式,电脑不知什么模式。
//htons: host(主机字节序) to net(网络字节序) short(2个字节)
seraddr.sin_port = htons(MYPORT);//设置地址的端口号信息
seraddr.sin_addr.s_addr = inet_addr(SERADDR);//设置IP地址
ret = bind(sockfd, (const struct sockaddr *)&seraddr, sizeof(seraddr));
if (ret < 0)
{
perror("bind");
return -1;
}
printf("bind success.\n");
//第三步: listen监听端口
ret = listen(sockfd, BACKLOG);
if (ret < 0)
{
perror("listen");
return -1;
}
//第四步:accept阻塞等待客户端接入
clifd = accept(sockfd, (struct sockaddr *)&cliaddr, &len);
printf("连接已经建立,client fd = %d.\n", clifd);
//客户端反复给服务器发
while (1)
{
//回合中第1步:服务器收
ret = recv(clifd, recvbuf, sizeof(recvbuf), 0);
//printf("成功接受了%d个字节\n", ret);
printf("client发送过来的内容是:%s\n", recvbuf);
memset(recvbuf, 0, sizeof(recvbuf));
//回合中第2步:服务器解析客户端数据包,然后干活
//回合中第3步:回复客户端
ret = send(clifd, "OK", 2, 0);
}
return 0;
}
client.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
//客户端是自动分配端口号
#define SERADDR "192.168.30.128" //服务器开放给我们的IP地址和端口号
#define SERPORT 9003
char sendbuf[100];
char recvbuf[100];
int main(void)
{
//第1步:先socket打开文件描述符
int sockfd = -1, ret = -1;
struct sockaddr_in seraddr = {0};//服务器的地址
//第1步:socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == sockfd)
{
perror("socket");
return -1;
}
printf("socketfd = %d.\n", sockfd);
//第2步:connect连接服务器
seraddr.sin_family = AF_INET;//设置地址族为IPv4
//网络字节序是大端模式,电脑不知什么模式。
//htons: host(主机字节序) to net(网络字节序) short(2个字节)
seraddr.sin_port = htons(SERPORT);//设置地址的端口号信息
seraddr.sin_addr.s_addr = inet_addr(SERADDR);//设置IP地址
ret = connect(sockfd, (const struct sockaddr *)&seraddr, sizeof(seraddr));
if (ret < 0)
{
perror("connect");
return -1;
}
printf("成功建立连接\n");
while (1)
{
//回合中第1步:客户端给服务器发送信息
printf("请输入要发送的内容\n");
scanf("%s",sendbuf);
//printf("刚才输入的是:%s", sendbuf);
ret = send(sockfd, sendbuf, strlen(sendbuf), 0);
printf("发送了%d个字符\n", ret);
//回合中第2步:客户端接收服务器的回复
memset(recvbuf, 0, sizeof(recvbuf));
ret = recv(sockfd, recvbuf, sizeof(recvbuf), 0);
//printf("成功接受了%d个字节\n", ret);
printf("server发送过来的内容是:%s\n", recvbuf);
//回合中第三步:客户端解析服务器的回复,再做下一步定夺
}
return 0;
}