客户端,服务器通信模型
创建套接字
int socket(int domain,int type,int protocol);
domain:协议族
AF_UINX(本地套接字),
AF_INET(网络套接字)
type:套接字通信类型
SOCK_STREAM:有序,可靠,面向连接的双向字节流
SOCK_STRDGRAM数据报服务,UDP
protocol:使用的协议
命名套接字
bind系统调用把参数address中的地址分配给与文件描述符socket关联的未命名套接字
int bind(int socket,const struct sockaddr *address,size_t address_len);
创建套接字队列
为了在套接字上接受进入的连接,服务器需要创建一个队列来保持未处理的请求
int listen(int socket,int backlog);
接受连接
一旦服务器程序创建并命名了套接字后,它就可以通过accept系统调用来等待客户建立套接字连接。
int accept(int socket,struct sockaddr*address,size_t *address_len);
如果套接字队列中有没有处理的连接,accept将阻塞直到有客户建立连接为止。可以通过对套接字设置O_NONBLOCK标志来改变这一行为
int flags = fcntl(socket,F_GETFL,0);
fcntl(socket,F_SETFL,O_NONBLOCK | flags);
请求连接
客户程序通过在一个未命名套接字和服务器监听套接字之间建立连接的方法来连接到服务器
int connect(int socket.const struct sockaddr *addrsss,size_t address_len);
参数socket指定的套接字将连接到参数address指定的服务器套接字。
服务端程序
1)打印客户端的ip与port
2)将接收到的数据进行大写转换并回显
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<stdio.h>
#include<sys/un.h>
#include<unistd.h>
#include<stdlib.h>
#include<signal.h>
#include<assert.h>
#include<string.h>
#include<ctype.h>
#include<errno.h>
#define SERVER_PORT 6666
static void sys_error(const char *str)
{
perror(str);
exit(1);
}
int main(int argc,char *argv[])
{
int lfd = 0,cfd = 0;
int ret;
char buffer[BUFSIZ,client_ip[56];
struct sockaddr_in serv_addr,clit_addr;
socklen_t clit_addr_len,client_ip_len;
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(SERVER_PORT);
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
lfd = socket(AF_INET,SOCK_STREAM,0);
if(lfd == -1)
sys_error("socket error");
bind(lfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));
listen(lfd,128);
socklen_t client_addrlength = sizeof(clit_addr);
cfd = accept(lfd,(struct sockaddr *)&clit_addr,&client_addrlength);
if(cfd < 0)
printf("error is:%d\n",errno);
printf("client ip:%s,port=%d\n", inet_ntop(AF_INET,&clit_addr.sin_addr.s_addr,client_ip,sizeof(client_ip)),
ntohs(clit_addr.sin_port));
while(1){
ret = read(cfd,buffer,sizeof(buffer));
write(STDOUT_FILENO,buffer,ret);
for(int i = 0;i<ret;i++)
{
buffer[i]=toupper(buffer[i]);
}
write(cfd,buffer,ret);
}
close(cfd);
close(lfd);
return 0;
}
服务端
(base) wy@ubuntu:~/network$ ./serv2
client ip:127.0.0.1,port=54192
hello
客户端
(base) root@ubuntu:/home/wy/network# nc 127.0.0.1 6666
hello
HELLO
客户端程序
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<stdio.h>
#include<sys/un.h>
#include<unistd.h>
#include<stdlib.h>
#include<signal.h>
#include<assert.h>
#include<string.h>
#include<ctype.h>
#include<errno.h>
#define SERVER_PORT 6666
static void sys_error(const char *str)
{
perror(str);
exit(1);
}
int main(int argc,char *argv[])
{
int cfd = 0;
int ret;
char buffer[BUFSIZ];
struct sockaddr_in serv_addr;
socklen_t clit_addr_len,client_ip_len;
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(SERVER_PORT);
inet_pton(AF_INET,"127.0.0.1",&serv_addr.sin_addr);
cfd = socket(AF_INET,SOCK_STREAM,0);
if(cfd == -1)
sys_error("socket error");
ret = connect(cfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));
if(ret != 0)
sys_error("connect error\n");
while(1){
write(cfd,"hello\n",6);
ret = read(cfd,buffer,sizeof(buffer));
printf("buffer=%s\n",buffer);
sleep(1);
}
close(cfd);
return 0;
}
注:inet_pton(AF_INET,“127.0.0.1”,&serv_addr.sin_addr);
服务端
(base) root@ubuntu:/home/wy/network# ./serv2
client ip:127.0.0.1,port=54204
hello
hello
客户端
(base) wy@ubuntu:~/network$ ./client2
buffer=HELLO
buffer=HELLO