linux下简单的流服务器程序

来源:互联网 发布:设置软件 双网卡 编辑:程序博客网 时间:2024/06/05 11:05
这个服务器所有的工作就是给远程的终端发送一个字符串:“Hello,World!”你所需要
做的就是在命令行上启动这个服务器,然后在另外一台机器上使用telnet 连接到这台我们
自己写的服务器上:
$ telnet remotehostname 4000
remotehostname 就是你运行我们自己写的服务器的那台机器名。
服务器代码:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
/* 服务器要监听的本地端口 */
#define MYPORT 4000
/* 能够同时接受多少没有accept 的连接 */
#define BACKLOG 10
main()
{
/* 在sock_fd 上进行监听,new_fd 接受新的连接 */
int sock_fd, new_fd ;
/* 自己的地址信息 */
struct sockaddr_in my_addr;
/* 连接者的地址信息*/
struct sockaddr_in their_addr;
int sin_size;
/* 这里就是我们一直强调的错误检查.如果调用socket() 出错,则返回 */ if ((sockfd =
- 162 - Linux网络编程
socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
/* 输出错误提示并退出 */
perror(“socket”);
exit(1);
}
/* 主机字节顺序 */
my_addr.sin_family = AF_INET;
/* 网络字节顺序,短整型 */
my_addr.sin_port = htons(MYPORT);
/* 将运行程序机器的IP 填充入s_addr */
my_addr.sin_addr.s_addr = INADDR_ANY;
/* 将此结构的其余空间清零 */
bzero(&(my_addr.sin_zero), 8);
/* 这里是我们一直强调的错误检查!! */ if (bind(sockfd, (struct sockaddr *)&my_addr,
sizeof(struct sockaddr)) == -1)
{
/* 如果调用bind()失败,则给出错误提示,退出 */
perror(“bind”);
exit(1);
}
/* 这里是我们一直强调的错误检查!! */
if (listen(sockfd, BACKLOG) == -1)
{
/* 如果调用listen 失败,则给出错误提示,退出 */
perror(“listen”);
exit(1);
}
while(1)
{
/* 这里是主accept()循环 */
sin_size = sizeof(struct sockaddr_in);
/* 这里是我们一直强调的错误检查!! */
第6 章 berkeley 套接字- 163 -
if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1)
{
/* 如果调用accept()出现错误,则给出错误提示,进入下一个循环 */
perror(“accept”);
continue;
}
/* 服务器给出出现连接的信息 */
printf(“server: got connection from %s/n”, inet_ntoa(their_addr.sin_addr));
/* 这里将建立一个子进程来和刚刚建立的套接字进行通讯 */
if (!fork())
/* 这里是子进程 */
/* 这里就是我们说的错误检查! */
if (send(new_fd, “Hello, world!/n”, 14, 0) == -1)
{
/* 如果错误,则给出错误提示,然后关闭这个新连接,退出 */
perror(“send”);
close(new_fd);
exit(0);
}
/* 关闭new_fd 代表的这个套接字连接 */
close(new_fd);
}
}
/* 等待所有的子进程都退出 */
while(waitpid(-1,NULL,WNOHANG) > 0);
}
为了更清楚的描述这个套接字服务器的运行过程,我把所有的代码都写在了这个大大
的main()主函数中。如果你觉得分成几个子程序会清楚一些,你可以自己式着把这个程序
改成几个小函数。
你可以使用下面这个套接字客户端来得到 "Hello, World!"这个字符串。
6.8.2 简单的流式套接字客户端程序
这个程序比起服务器端程序要简单一些。它所做的工作就是connect()到服务器的4000
端口,然后把服务器发送的字符串给显示出来。
客户端程序:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
- 164 - Linux网络编程
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
/* 服务器程序监听的端口号 */
#define PORT 4000
/* 我们一次所能够接收的最大字节数 */
#define MAXDATASIZE 100
int
main(int argc, char *argv[])
{
/* 套接字描述符 */
int sockfd, numbytes;
char buf[MAXDATASIZE];
struct hostent *he;
/* 连接者的主机信息 */
struct sockaddr_in their_addr;
/* 检查参数信息 */
if (argc != 2)
{
/* 如果没有参数,则给出使用方法后退出 */
fprintf(stderr,“usage: client hostname/n”);
exit(1);
}
/* 取得主机信息 */
if ((he=gethostbyname(argv[1])) == NULL)
/* 如果gethostbyname()发生错误,则显示错误信息并退出 */
herror(“gethostbyname”);
exit(1);
}
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
/* 如果socket()调用出现错误则显示错误信息并退出 */
perror(“socket”);
exit(1);
}
/* 主机字节顺序 */
their_addr.sin_family = AF_INET;
/* 网络字节顺序,短整型 */
their_addr.sin_port = htons(PORT);
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
/* 将结构剩下的部分清零*/
bzero(&(their_addr.sin_zero), 8);
if(connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1)
{
/* 如果connect()建立连接错误,则显示出错误信息,退出 */
perror(“connect”);
exit(1);
}
if((numbytes=recv(sockfd, buf, MAXDATASIZE, 0)) == -1)
{
/* 如果接收数据错误,则显示错误信息并退出 */
perror(“recv”);
exit(1);
}
buf[numbytes] = ‘/0’;
printf(“Received: %s”,buf);
close(sockfd);
return 0;
}
注意:显然,你必须在运行client 之前先启动server。否则client 的执行会出错(显示“Connection
refused”)。