TCP/IP网络编程1 实现最简单的hello_world服务器 hello_world客户端 编译运行

最近在看《TCP/IP网络编程》这本书,很佩服作者能把几十行的代码扩展成一本书大小。

就写个博客记录一下学习心得吧。

当然只选择性看了这本书的Linux部分,Windows编码部分直接跳过了,如果以后用到Windows下编程再去看吧。。。

hello_server.c

#include <stdio.h>   
#include <stdlib.h>   
#include <string.h>   
#include <unistd.h>   
#include <arpa/inet.h>   
#include <sys/socket.h>   
   
void error_handling(char *message);   
   
int main(int argc, char *argv[])   
{   
    int serv_sock;   
    int clnt_sock;   
   
    struct sockaddr_in serv_addr;   
    struct sockaddr_in clnt_addr;   
    socklen_t clnt_addr_size;   
   
    char message[]="Hello World!";   
       
    if(argc!=2){   
        printf("Usage : %s <port>
", argv[0]);   
        exit(1);   
    }   
       
    serv_sock=socket(PF_INET, SOCK_STREAM, 0);   
    if(serv_sock == -1)   
        error_handling("socket() error");   
       
    memset(&serv_addr, 0, sizeof(serv_addr));   
    serv_addr.sin_family=AF_INET;   
    serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);   
    serv_addr.sin_port=htons(atoi(argv[1]));   
       
    if(bind(serv_sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr))==-1 )   
        error_handling("bind() error");    
       
    if(listen(serv_sock, 5)==-1)   
        error_handling("listen() error");   
       
    clnt_addr_size=sizeof(clnt_addr);     
    clnt_sock=accept(serv_sock, (struct sockaddr*)&clnt_addr,&clnt_addr_size);   
    if(clnt_sock==-1)   
        error_handling("accept() error");     
       
    write(clnt_sock, message, sizeof(message));   
    close(clnt_sock);      
    close(serv_sock);   
    return 0;   
}   
   
void error_handling(char *message)   
{   
    fputs(message, stderr);   
    fputc('
', stderr);   
    exit(1);   
} 

socket函数创建套接字

bind函数分配IP和端口号

listen函数将套接字转为可接收连接状态

accept函数受理连接请求,在没有连接的情况下调用accept则不会返回,直到有连接请求

write函数用于向文件中输出数据。Linux中不区分文件和套接字,所以通过套接字向其他计算机传递数据时也使用这个函数。

将数据写入文件

#include <unistd.h> 

ssize_t write(int fd, const void * buf, size_t nbytes);

fd 显示数据传输对象的文件描述符

buf 要传输数据的缓冲地址值

nbytes 要传输的字节数

读取文件中的数据

#include <unistd.h> 

ssize_t read(int fd, void * buf, size_t nbytes);

fd 显示数据接收对象的文件描述符

buf 要保存接收数据的缓冲地址值

nbytes 要接收的字节数

hello_world客户端

hello_clint.c

#include <stdio.h>   
#include <stdlib.h>   
#include <string.h>   
#include <unistd.h>   
#include <arpa/inet.h>   
#include <sys/socket.h>   
   
void error_handling(char *message);   
   
int main(int argc, char* argv[])   
{   
    int sock;   
    struct sockaddr_in serv_addr;   
    char message[30];   
    int str_len;   
       
    if(argc!=3){   
        printf("Usage : %s <IP> <port>
", argv[0]);   
        exit(1);   
    }   
       
    sock=socket(PF_INET, SOCK_STREAM, 0);   
    if(sock == -1)   
        error_handling("socket() error");   
       
    memset(&serv_addr, 0, sizeof(serv_addr));   
    serv_addr.sin_family=AF_INET;   
    serv_addr.sin_addr.s_addr=inet_addr(argv[1]);   
    serv_addr.sin_port=htons(atoi(argv[2]));   
           
    if(connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr))==-1)    
        error_handling("connect() error!");   
       
    str_len=read(sock, message, sizeof(message)-1);   
    if(str_len==-1)   
        error_handling("read() error!");   
       
    printf("Message from server: %s 
", message);     
    close(sock);   
    return 0;   
}   
   
void error_handling(char *message)   
{   
    fputs(message, stderr);   
    fputc('
', stderr);   
    exit(1);   
}

编译运行

编译并执行服务器

gcc hello_server.c -o hserver

 编译hello_server.c并生成可执行文件hserver

./hserver 9190

 运行hserver (监听端口号为9190)

编译并执行客户端

gcc hello_clint.c -o hclint

  编译hello_sclint.c并生成可执行文件hclint

./hclint 127.0.0.1 9190

 连接127.0.0.1主机(也就是本主机)的9190端口号

执行结果

Message from server:Hello world!

 传输完消息后,客户端和服务器都停止运行。