前两天我们已经知道了服务器端和客户端交互的过程
那么废话不多说,talk is cheap,直接上代码。(已做代码详细注释)
(先不考虑出错处理)
server.c
#include<stdio.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<string.h>//bzero
#include<arpa/inet.h>//inet_ntop
#include<sys/types.h>//fd
#include<unistd.h>
#define SERVER_PORT 8000
#define MAXLINE 4096
int main(){
struct sockaddr_in severaddr,clientaddr;//
int sockfd,addrlen,confd;
int len,i;
char ipstr[128]; //1.socket
sockfd=socket(AF_INET,SOCK_STREAM,0); //IPv4 TCP
//2.bind
//先初始化地址
bzero(&severaddr,sizeof(severaddr));//清空
//地址族协议IPv4
severaddr.sin_family=AF_INET;
//IP地址 //转成网络字节序
severaddr.sin_addr.s_addr=htonl(INADDR_ANY);//任意IP
//32位存储空间 "XXX.XX.XXX.XX"
//端口
severaddr.sin_port=htons(SERVER_PORT);
bind(sockfd,(struct sockaddr *)&severaddr,sizeof(severaddr));
//3.listen
listen(sockfd,128);
while(1){//从这里循环相应客户端
//4.accept阻塞监听客户端
addrlen=sizeof(clientaddr);
confd=accept(sockfd,(struct sockaddr *)&clientaddr,&addrlen);//传出客户端地址 传入传出
//成功返回一个新的fd 得到客户端信息
//输出客户端IP地址和端口号
//
inet_ntop(AF_INET,&clientaddr.sin_addr.s_addr,ipstr,sizeof(ipstr));//af协议,src,提供数组,str_len
//返回char*
printf("client ip %s\tport %d\n",
inet_ntop(AF_INET,&clientaddr.sin_addr.s_addr,ipstr,sizeof(ipstr)),
ntohs(clientaddr.sin_port));//接受到整型转成字符串 网络字节序转主机序
//交换数据用confd
//5、处理客户端请求
/*
如将客户端输入字符串转成大写后回送
*/
close(confd);
}
close(sockfd);
return 0;
}
于是我们可以用ifconfig查看自己的IP地址,可以局域网,也可以用固定的“127.0.0.1”;
在终端用nc 127.0.0.1 8000 (我们设置的端口号)测试我们的server
这时会打印客户端的IP以及随机的端口号,说明已经成功。
当然也可用当前局域网下的另一台机器输入命令,也会打印出其ip。
client.c
#include<netinet/in.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<stdlib.h>
#define SERVER_PORT 8000
int main(int argc,char **argv){
struct sockaddr_in severaddr;
int confd;
char ipstr[]="XXX.XXX.XX.XXX";
//1.创建一个socket
confd=socket(AF_INET,SOCK_STREAM,0);
//2.connect前知道自己服务器的ip和端口号
//初始化服务器地址
bzero(&severaddr,sizeof(severaddr));
severaddr.sin_family=AF_INET;
inet_pton(AF_INET,ipstr,&severaddr.sin_addr.s_addr);//ip地址转换
severaddr.sin_port=htons(SERVER_PORT);
//3.链接服务器
//没有调bind,分配一个随机的端口号使用
connect(confd,(struct sockaddr*)&severaddr,sizeof(severaddr));//fd,地址记得强转,结构体长度
//4.请求服务器处理数据
//暂不做处理
//5.关闭socket
close(confd);
return 0;
}
这时写一个makefile,启动server,这时运行client。
Makefile:
all:sever client
sever:sever.c
gcc $< -o $@
client:client.c
gcc $< -o $@
.PHONY:clean
clean:
rm -f sever
rm -f client
便会在server打印如图:
说明我们的客户端也是好的。
是不是很神奇呢。
当然接下来我们也可以让server来处理一些数据并返回给client。
参考:
APUE以及itcast-Linux系统编程