基于TCP的C/S程序设计

1算法流程

2代码及注释

server.c

#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#define CHARNUM 100
int main()
{
        int sockfd,connfd,n;
        char send_buf[CHARNUM],recv_buf[CHARNUM],addr[INET_ADDRSTRLEN];
        struct sockaddr_in server_addr,client_addr;
        socklen_t client_addr_len;
        sockfd=socket(AF_INET,SOCK_STREAM,0);//建立一个套接字
        bzero(&server_addr,sizeof(server_addr));//清空地址
        server_addr.sin_addr.s_addr=htonl(INADDR_ANY);//地址为0.0.0.0
        server_addr.sin_family=AF_INET;
        server_addr.sin_port=htons(8000);//端口8000
        bind(sockfd,(struct sockaddr *)&server_addr,sizeof(server_addr));//将地址与套接字捆绑
        listen(sockfd,10);//监听申请的连接
        printf("WAIT...\n");
        while(1)
        {
                client_addr_len=sizeof(client_addr);
                connfd=accept(sockfd,(struct sockaddr *)&client_addr,&client_addr_len);//套接字接受的一个连接
                if(connfd>0)
                {
                        printf("client's IP:%s\n",inet_ntop(AF_INET,&client_addr.sin_addr,addr,INET_ADDRSTRLEN));
                        break;
                }
        }
        while(1)
        {
                
                n=read(connfd,recv_buf,CHARNUM);//接收数据
                printf("client say:%s\n",recv_buf);
                if(strcmp(recv_buf,"quit")==0)
                {
                        printf("client exited!");
                        break;
                }
                printf("reply:");
                scanf("%s",send_buf);    
                if(strcmp(send_buf,"quit")==0)
                {
                        strcpy(send_buf,"SERVER CLOSED!");
                        write(connfd,send_buf,20);
                        break;
                }
                write(connfd,send_buf,100);//发送数据
        }
        printf("server is closed!\n");
        close(sockfd);关闭链接
        return 0;
}

client.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#define CHARNUM 100
int main()
{
        int sockfd,n;
        struct sockaddr_in server_addr,client_addr;
        char send_buf[CHARNUM],recv_buf[CHARNUM],addr[INET_ADDRSTRLEN];
        sockfd=socket(AF_INET,SOCK_STREAM,0);
        bzero(&server_addr,sizeof(server_addr));
        server_addr.sin_family=AF_INET;
        server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
        server_addr.sin_port=htons(8000);
        connect(sockfd,(struct sockaddr*)&server_addr,sizeof(server_addr));//建立与指定socket的连接
        while(1)
        {
                printf("send to server:");
                scanf("%s",send_buf);
                write(sockfd,send_buf,CHARNUM);
                if(strcmp(send_buf,"quit")==0)
                {
                        printf("CLOSED!\n");
                        break;
                }
                n=read(sockfd,recv_buf,CHARNUM);
                if(strcmp(recv_buf,"SERVER CLOSED!")==0)
                {
                        printf("SERVER CLOSED!\n");
                        break;                        
                }
                printf("server:%s\n",recv_buf);
        }
        close(sockfd);
        return 0;
}

3效果:

4代码中所用系统调用与结构体说明:

htonl()

将主机数转换成无符号长整型的网络字节顺序。本函数将一个32位数从主机字节顺序转换成网络字节顺序。

INADDR_ANY就是指定地址为0.0.0.0的地址。

htons是将整型变量从主机字节顺序转变成网络字节顺序。

需要注意的是:

sockaddr和sockaddr_in二者的占用的内存大小是一致的,因此可以互相转化,从这个意义上说,他们并无区别。

sockaddr常用于bind、connect、recvfrom、sendto等函数的参数,指明地址信息。是一种通用的套接字地址。而sockaddr_in 是internet环境下套接字的地址形式。所以在网络编程中我们会对sockaddr_in结构体进行操作。使用sockaddr_in来建立所需的信息,最后使用类型转化就可以了。

posted @ 2017-12-13 20:33  奇热行  阅读(302)  评论(0)    收藏  举报