socket通讯的简单实现(C)

服务端多线程版本代码:

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>

#define SERVER_PORT 9002              // 判断是否被占用 netstat -an | grep 9001
#define LENGTH_OF_LISTEN_QUEUE 10     // 监听客户端链接数量

void handle_client_connect(void *new_server_socket);

int main()
{
    printf("server start ......\n");

    struct sockaddr_in server_addr;
    memset(&server_addr,0x00,sizeof(struct sockaddr_in));

    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htons(INADDR_ANY);    // 必须是网络字节序(大端)
    server_addr.sin_port = htons(SERVER_PORT);          // 必须是网络字节序(大端)
   int  server_socket;
    server_socket = socket(AF_INET,SOCK_STREAM,0);                             // socket
    bind(server_socket,(struct sockaddr *)&server_addr,sizeof(server_addr));   // bind
    listen(server_socket,LENGTH_OF_LISTEN_QUEUE);                  // listen

    struct sockaddr_in client_addr;
    socklen_t length = sizeof(client_addr);

    while(1){
        pthread_t threadnew;
        int new_server_socket = accept(server_socket,(struct sockaddr *)&client_addr,&length);
        printf("start clinet connect!\n");

        pthread_create(&threadnew, NULL, (void *)(&handle_client_connect), (void *)(&new_server_socket));
    }

    close(server_socket);
    return 0;
}

void handle_client_connect(void *new_server_socket){
    int cli_socket = *((int *)new_server_socket);
    while(1)
    {
        char recvbuf[1024];
        memset(recvbuf,0x00,sizeof(recvbuf));
        int rlength = recv(cli_socket,recvbuf,1024,0);
        printf("recv buf len is [%d]\n", rlength);
        recvbuf[rlength] = '\0';
        if(strncmp(recvbuf,"q", 1) == 0)
        {
              printf("clent quit!\n");
            break;
        }
        printf("recv from client:[%s]\n",recvbuf);
    }
    close(cli_socket);
    pthread_exit(NULL);

服务端代码:

#include <stdio.h>
#include <sys/types.h>    // socket()
#include <sys/socket.h>   // socket() bind() listen() accept() recv()
#include <arpa/inet.h>    // htons() htonl()
#include <string.h>       // strerror()
#include <errno.h>        // errno
#include <unistd.h>       // close()
#include <stdlib.h>       // exit()

#define SERVER_PORT 9001      // 检测是否被占用 netstat -an | grep 9001
#define MAX_CONNECT_NUM 10    // 最大连接数 
#define RECV_LENGTH 1024      // recv 接收的字节数

int main(){

    printf("sercer start...\n");
    int ret = -1;

    // socket()
    int server_socket = socket(AF_INET, SOCK_STREAM, 0);

    // bind()
    struct sockaddr_in  server_in;
    memset(&server_in, 0x00, sizeof(struct sockaddr_in));
    server_in.sin_family = AF_INET;
    server_in.sin_addr.s_addr = htonl(INADDR_ANY);    // 转换为网络字节序(大端)
    server_in.sin_port = htons(SERVER_PORT);          // 转换为网络字节序(大端)
    ret = bind(server_socket, (struct sockaddr *)&server_in, sizeof(server_in));
    if(-1 == ret){
        printf("bind error[%s, errno:%d]\n", strerror(errno), errno);
        exit(0);
    }

    // listen()
    ret = listen(server_socket, MAX_CONNECT_NUM);
    if(-1 == ret){
        printf("listen error[%s, errno:%d]\n", strerror(errno), errno);
        exit(0);
    }

    // accept()
    char recvbuf[RECV_LENGTH];
    memset(recvbuf, 0x00, sizeof(recvbuf));
    
    while(1){
        int new_server_socket = accept(server_socket, (struct sockaddr *)NULL, NULL);  // 阻塞模式
        if(-1 == new_server_socket){
            printf("server accept error[%s, errno:%d]\n", strerror(errno), errno);
            continue;
        }
        printf("client connnect success...\n");

        int length = recv(new_server_socket, recvbuf, RECV_LENGTH, 0);
        recvbuf[length] = '\0';
        printf("client:[%s]\n", recvbuf);
        close(new_server_socket);
    }
    
    // close()
    close(server_socket);

    return 0;
}

客户端代码:

#include <stdio.h>
#include <sys/types.h>   // socket()
#include <sys/socket.h>  // socket() connect() send() close()
#include <arpa/inet.h>   // inet_pton()
#include <string.h>      // strerror
#include <errno.h>       // errno
#include <stdlib.h>      // exit()

#define SERVER_PORT 9001  // 服务端端口号

int main(){
    printf("client start...\n");

    int ret = -1;

    // socket()
    int client_socket = socket(AF_INET, SOCK_STREAM, 0);

    // connect()
    struct sockaddr_in client_in;
    memset(&client_in, 0x00, sizeof(client_in));
    client_in.sin_family = AF_INET;
    client_in.sin_port = htons(SERVER_PORT);  // 必须是网络字节序(大端)
    ret = inet_pton(AF_INET, "127.0.0.1", &client_in.sin_addr);
    if(ret < 0){
        printf("inet_pton error[%s, errno:%d]\n", strerror(errno), errno);
        exit(0);
    }
    ret = connect(client_socket, (struct sockaddr *)&client_in, sizeof(client_in));
    if(ret < 0){
        printf("connect error[%s, errno:%d]\n", strerror(errno), errno);
        exit(0);
    }

    // send()
    char sendbuf[1024];
    memset(sendbuf, 0x00, sizeof(sendbuf));
    printf("client input:\n");
    gets(sendbuf);
    int in_length = strlen(sendbuf);
    sendbuf[in_length] = '\0';

    ret = send(client_socket, sendbuf, 1024, 0);
    if(ret < 0){
        printf("send error[%s, errno:%d]\n", strerror(errno), errno);
        exit(0);
    }

    // close()
    close(client_socket);
    return 0;
}

Makefile:

CC=cc

all:server client 
cleanlist=server client *.o

server:server.o
	${CC} $@.c -o $@ 

client:client.o
	${CC} $@.c -o $@ 

clean:
	rm -f ${cleanlist} 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
《网络程序设计》课程设计 基于socket的聊天系统设计 摘要:本设计通过研究讨论,设计基于socket编程的网络聊天系统,服务器端采用多线程并发服务方式,多客户端能同时连接服务器,并且客户端之间能进行通信。程序通过了验证与测试,证明了系统的可用性、易用性、完善性。 关键词:socketserver、client、聊天系统 引言 socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过"套接字"向网络发出请求或者应答网络请求。一个聊天系统的通信模块就是Socket程序的设计与实现,聊天系统分为服务器端和客户端,服务器端的任务就是接受客户端的不同请求,做出不同的响应,并处理多客户端之间的通信。 3.1头文件 /************************************************************ *chat.h * 基于socket的聊天客户机和服务器的头文件 *设计思路: * 客户机提出各种请求,服务器根据不同请求,发送不同的响应. *关键问题: * 客户机和服务器之间协议制订 *************************************************************/ #include // for sockaddr_in #include // for socket #include // for socket #include // for printf #include // for exit #include // for bzero /************************************************************ *服务器端口定义 *************************************************************/ #define CHAT_SERVER_PORT (6666) /************************************************************ *报文类型定义 *************************************************************/ #define NO_COMMAND (100) //客户端发送报文类型 #define REGISTER (1) #define LOGIN (2) #define GET_USER_LIST (3) #define TALK_TO (4) #define EXIT (5) #define CHANGE (6) #define GET_MESSAGE (7) //服务器端发送报文类型
最新版Socket编程,后面带有程序实例,并通过调试,可以直接编译运行;希望对大家有帮助。代码设计服务端、客户端socket实例,设计IPV4、IPV6的实例代码。 网络的Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符。Socket也具有一个类似于打开文件的函数调用Socket(),该函数返回一个整型的Socket描述符,随后的连接建立、数据传输等操作都是通过该Socket实现的。 部分代码(服务器): #include #include #include #include #include #include #include #include #define SERVPORT 3333 /*服务器监听端口号 */ #define BACKLOG 10 /* 最大同时连接请求数 */ main() { int sockfd,client_fd; /*sockfd:监听socket;client_fd:数据传输socket */ struct sockaddr_in my_addr; /* 本机地址信息 */ struct sockaddr_in remote_addr; /* 客户端地址信息 */ if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror( "socket创建出错!"); exit(1); } my_addr.sin_family=AF_INET; my_addr.sin_port=htons(SERVPORT); 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) { perror( "bind出错!"); exit(1); } if (listen(sockfd, BACKLOG) == -1) { perror( "listen出错!"); exit(1); } while(1) { sin_size = sizeof(struct sockaddr_in); if ((client_fd = accept(sockfd, (struct sockaddr *) &remote;_addr, &sin;_size)) == -1) { perror( "accept出错"); continue; } printf( "received a connection from %s\n", inet_ntoa(remote_addr.sin_addr)); if (!fork()) { /* 子进程代码段 */ if (send(client_fd, "Hello, you are connected!\n", 26, 0) == -1) perror( "send出错!"); close(client_fd); exit(0); } close(client_fd); } } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值