一个简单的服务器与客户端程序
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结构再传入系统调用函数中。
这样就稳了~
并未使用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结构再传入系统调用函数中。
这样就稳了~
相关文章推荐
- 本程序说明了如何建立一个简单的可以接收UDP服务器数据的UDP客户端
- 【UNP学习笔记】一个简单的服务器/客户端程序
- 【实验 1-2】编写一个简单的 UDP 服务器和 UDPP 客户端程序。程序均为控制台程序窗口。
- libevent实现的一个简单的服务器和客户端程序
- 【实验 1-1】编写一个简单的 TCP 服务器和 TCP 客户端程序。程序均为控制台程序窗口。
- 用Java实现一个简单的服务器与客户端程序
- 一个简单的基于node.js的TCP服务器和基于C++的TCP客户端通信示例程序
- Java编写一个简单的TCP通信程序。服务器发送一条字符串,客户端接收该信息并显示。
- 使用jrtplib写的一个简单服务器和客户端程序
- ACE+线程池实现一个简单的服务器+多客户端通信程序
- 一个简单的UDP程序—C++服务器和C# .NET客户端
- TCP/TP编程 - 一个简单的Linux下C写的socket服务器客户端程序
- Python一个简单的通信程序(客户端 服务器)
- 一个简单的服务器和客户端的心跳程序
- 简单的客户端服务器通信程序
- 一个简单的socket服务端和客户端程序:客户端发送数据给服务端,服务端接收到数据后再给客户端发送数据
- 由一个简单的客户端间TCP/UDP通信程序引发的关于设计模式的思考
- 一个简单的TCP 客户端时间获取程序 ipv4/ipv6
- 用消息队列编写一个客户端服务器通信的程序
- 非阻塞式服务器和客户端程序(TCP)【简单的原理例子】