对于计算机世界来说,每个方法和数据结构都是我们现实生活的一个投影和体现,希望我对于网络通信和socket的一些理解能够给你带来帮助。
通信的目的地址
使用的端口号http 80 smtp 25
使用的传输层协议(如TCP、UDP)
我们如果去寄信,信件写上地址和你准备寄给谁并把它放到邮筒中(邮局),对方也有个小邮筒用来接收别人发给它的信件,如果对方的地址是你填的地址的话信件就收下,那样对方才能够接收得到(对方也就知道了你的地址,也可以给你回信),如果我们只写了地址,没写姓名的话那么同一家人他们也不知道是给谁得信。
分析:
两个邮筒就相当于Socket,地址就是三要素中的目的地址(IP地址),而端口号就是姓名,因为就像你去访问www.baidu.com我们http默认访问80端口,对于服务器来说不一样的端口号对应不一样的作用,如果没有端口号也就不知道你到底想干什么,如果你访问的是像百度那么如果你发出请求服务器端接收到了同意你的请求就会反馈给你想要的信息(给你个界面),而如果你想要在网络上就必须要遵守约定和协议,那么就要用到传输层协议。
利用socket实现一个简单的回声服务器
客户端对服务器进行连接,并且发送数据,服务器接收到了以后反馈给客户端一些信息
echo_server.c
#include
#include
#include
#include
#include
#include
#include
#define SERVER_PORT 666
int main(void){
int sock;//代表信箱
struct sockaddr_in server_addr;
//1.美女创建信箱
sock = socket(AF_INET, SOCK_STREAM, 0);
//2.清空标签,写上地址和端口号,清理再写养成好习惯
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;//选择协议族IPV4
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);//监听本地所有IP地址,主机字节序转换成网络字节序
server_addr.sin_port = htons(SERVER_PORT);//绑定端口号
//实现标签贴到收信得信箱上,绑定地址
bind(sock, (struct sockaddr *)&server_addr, sizeof(server_addr));
//把信箱挂置到传达室,这样,就可以接收信件了,最多可以同时接收128封信,如果有第129封则接收失败
listen(sock, 128);
//万事俱备,只等来信
printf("等待客户端的连接\n");
int done =1;
while(done){
struct sockaddr_in client;
int client_sock, len;
char client_ip[64];//存放客户端的ip地址
char buf[256];//存放客户端的端口号
socklen_t client_addr_len;
client_addr_len = sizeof(client);
//记录一下刚刚和该服务器发送信件的客户端的地址并产生一个socket
client_sock = accept(sock, (struct sockaddr *)&client, &client_addr_len);
//打印客户端IP地址和端口号
printf("client ip: %s\t port : %d\n",
inet_ntop(AF_INET, &client.sin_addr.s_addr,client_ip,sizeof(client_ip)),
ntohs(client.sin_port));
/*读取客户端发送的数据*/
len = read(client_sock, buf, sizeof(buf)-1);
buf[len] = '\0';
printf("receive[%d]: %s\n", len, buf);
//转换成大写
for(i=0; i<len; i++){
buf[i] = toupper(buf[i]);
}
//发送信息回去
len = write(client_sock, buf, len);
printf("finished. len: %d\n", len);
close(client_sock);//关闭交流的通道
}
close(sock);
return 0;
}
echo_client.c
#include
#include
#include
#include
#include
#include
#define SERVER_PORT 666
#define SERVER_IP "127.0.0.1"
int main(int argc, char *argv[]){
int sockfd;
char *message;
struct sockaddr_in servaddr;
int n;
char buf[64];
//argc就是输入了的命令数目:./echo_client "this is test"在这argc=2
if(argc != 2){
fputs("Usage: ./echo_client message \n", stderr);
exit(1);
}
message = argv[1];//argv[0]就是编译的文件:./echo_client "this is test"
printf("message: %s\n", message);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&servaddr, '\0', sizeof(struct sockaddr_in));
servaddr.sin_family = AF_INET;
inet_pton(AF_INET, SERVER_IP, &servaddr.sin_addr);
servaddr.sin_port = htons(SERVER_PORT);
connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));//建立连接
write(sockfd, message, strlen(message));
n = read(sockfd, buf, sizeof(buf)-1);
if(n>0){
buf[n]='\0';
printf("receive: %s\n", buf);
}else {
perror("error!!!");
}
printf("finished.\n");
close(sockfd);
return 0;
}
总结:
对于服务器端和客户端方面不同地方在于,服务器端就相当于对方的邮筒,拿来收信件要绑定地址(不能随意更改),而客户端就像是我们写信只要写上对方的地址和是谁(端口号)想要对谁进行连接就好不用去绑定地址,当你发送信件给对方时对方也就可以知道你的地址(可以用一个socket来保存住,那样它就可以根据你的地址对你进行回信)