您的位置:首页 > 其它

一个简单的服务器与客户端程序

2016-11-19 21:25 447 查看
最近在学习《深入理解计算机系统》,看到linux系统级的IO以及,socket通信,所以干脆参考书上例程,自己着手写一个客户端与服务器的小程序。

并未使用csapp封装好的open_clientfd与open_listenfd还有RIO包

主要功能就两个:

1.服务器读客户端送入的字符串,并通知客户端已经收到。

2.客户端能主动退出连接。

写这个小程序是为了练习socket通信的步骤。

服务器:

socket函数创建套接字

bind将socket创建的套接字与服务器套接字绑定

listen打开监听套接字

accept等待客户端connect  //会阻塞

客户端:

socket创建套接字

connect将套接字与服务器ip地址绑定,建立Internet连接

之后客户端与服务器就能用各自的套接字,通过linux系统IO通信了!

运行的时候,客户端后需加服务器ip与端口,服务器需加开启的端口,分别为main函数参数

值得注意的是linux系统IO  read默认情况下是阻塞的

服务器代码:

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

int echo(int connfd){
char *exit = "exit is getted";
write(connfd, "Please input", 100);
while(1){
char client_word[100];
read(connfd, client_word, 100);
printf("%s \n", client_word);
strcat(client_word, " is getted");
write(connfd, client_word, 100);
if(strcmp(client_word, exit) == 0){
printf("client exit\n");
return 1;
}else{
continue;
}
}

}

int main(int argc, char **argv){
int port, listenfd, connfd, clientlen;
struct sockaddr_in clientadder;
struct hostent *hp;
port = atoi(argv[1]);

if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){//创建服务器套接字
printf( "socket error\n" );
}

clientadder.sin_family = AF_INET;//填充信息
clientadder.sin_addr.s_addr = htonl(INADDR_ANY);
clientadder.sin_port = htons(port);

if(bind(listenfd, (struct sockaddr *)&clientadder, sizeof(clientadder)) < 0){//绑定
printf( "bind error\n" );
}

if (listen(listenfd, 1024) < 0){//通知内核此套接字为服务器使用
printf( "listen error\n" );
}

while(1){
printf( "wait for client\n" );
clientlen = sizeof(clientadder);
if((connfd = accept(listenfd, (struct sockaddr *)&clientadder, &clientlen)) < 0){//监听
printf( "accept error\n" );
}else{
printf("connect successful!\n");
if (echo(connfd)){
printf("exit from echo\n");
}else{
printf("error from echo\n");
}
}
write(connfd, "exit", 100);
close(connfd);
}
printf("gg\n");

}


客户端代码:

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char **argv){
int port,clientfd;
struct hostent *hp;
char *EXIT = "exit is getted";
struct sockaddr_in serveraddr;

port = atoi(argv[2]);

if((hp = gethostbyname(argv[1])) == NULL){ //通过ip地址获取目的主机信息
printf("ip error\n");
}

if((clientfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){ //创建客户端套接字
printf("socket error\n");
}

bcopy((char *)hp->h_addr_list[0], (char *)&serveraddr.sin_addr.s_addr, hp->h_length);//填充信息
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(port);

if(connect(clientfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0){//创建连接
printf("connect error\n");
}else{
printf("connect successful!\n");
while(1){
char buf[100];
char get[100];
read(clientfd, get, 100);
if(strcmp(get, EXIT) == 0){
printf("server exit\n");
close(clientfd);
return 0;
}
printf("%s \n", get);
scanf("%s", buf);
write(clientfd, buf, 100);
}
}
return 0;
}


通过查阅其他资料得知:

struct sockaddr是通用的套接字地址,而struct sockaddr_in则是internet环境下套接字的地址形式,二者长度一样,都是16个字节。

二者是并列结构,指向sockaddr_in结构的指针也可以指向sockaddr。

一般情况下,需要把sockaddr_in结构强制转换成sockaddr结构再传入系统调用函数中。

这样就稳了~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐