客户端socket通信库

    socket通信属于IO操作,因此客户端通常会将要发送的数据一次性发送至服务器,待服务器处理后然后返回结果信息给客户端。趁着离职期间比较闲,写了个客户端socket通信库,日后用得着的话就可以直接用。

    目录中的文件有:compile.sh  libnetcom.so  netcom.c  netcom.h

    netcom.h文件内容有:

    

#ifndef _NETCOM_H_
#define _NETCOM_H_

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

typedef struct st_socket_t
{
    int socket;
    char *recv_buff;
    unsigned int cur_recv_index;
    char *send_buff;
    unsigned int cur_send_index;
    unsigned int max_buff_len;
}st_socket_t;

int create_socket(st_socket_t **pp_socket);
int nc_conn(st_socket_t *p_socket, char *ip, int port);
int nc_get_one_byte(st_socket_t *p_socket, char *val);
int nc_get_n_byte(st_socket_t *p_socket, void *val, unsigned int n);

int nc_put_one_byte(st_socket_t *p_socket, char *val);
int nc_put_n_byte(st_socket_t *p_socket, void *val, unsigned int n);

int nc_send(st_socket_t *p_socket);
int nc_recv(st_socket_t *p_socket);
#endif

    netcom.c文件内容有:

    

#include "netcom.h"

#define MAX_BUFF_LEN 8192

int create_socket(st_socket_t **pp_socket)
{
    st_socket_t *p_socket = NULL;

    p_socket = (st_socket_t *)malloc(sizeof(st_socket_t));
    memset(p_socket, 0, sizeof(st_socket_t));

    p_socket->socket = 0;
    p_socket->max_buff_len = MAX_BUFF_LEN;
    p_socket->recv_buff = (char *)malloc(sizeof(char) * MAX_BUFF_LEN);
    memset(p_socket->recv_buff, 0, sizeof(char) * MAX_BUFF_LEN);
    p_socket->send_buff = (char *)malloc(sizeof(char) * MAX_BUFF_LEN);
    memset(p_socket->send_buff, 0, sizeof(char) * MAX_BUFF_LEN);

    *pp_socket = p_socket;
    return 0;
}

int nc_conn(st_socket_t *p_socket, char *ip, int port)
{
    int ret = 0;
    struct sockaddr_in sockaddr;

    if (p_socket == NULL){
        perror("p_socket == NULL");
    }
    p_socket->socket = socket(AF_INET, SOCK_STREAM, 0);
    memset(&sockaddr, 0, sizeof(struct sockaddr_in));
    sockaddr.sin_family = AF_INET;
    sockaddr.sin_addr.s_addr = inet_addr(ip);
    sockaddr.sin_port = htons(port);

    ret = connect(p_socket->socket, &sockaddr, sizeof(struct sockaddr_in));

    return ret;
}

int nc_get_one_byte(st_socket_t *p_socket, char *val)
{
    if (val == NULL){
        return -1;
    }
        
    *val = p_socket->recv_buff[p_socket->cur_recv_index++];

    return 0;
}


int nc_get_n_byte(st_socket_t *p_socket, void *val, unsigned int n)
{
    int pos = p_socket->cur_recv_index;

    if (val == NULL){
        return -1;
    }
        
    memcpy(val, p_socket->recv_buff + pos, n);
    p_socket->cur_recv_index += n;

    return 0;
}

int nc_put_one_byte(st_socket_t *p_socket, char *val)
{
    int ret = 0;

    if (val == NULL){
        return -1;
    }
    
    p_socket->send_buff[p_socket->cur_send_index++] = *val;
    if (p_socket->cur_send_index == MAX_BUFF_LEN){
        ret = send(p_socket->socket, p_socket->send_buff, MAX_BUFF_LEN, 0);
        p_socket->cur_send_index = 0;
        return ret;
    }
    
    return 0;
}

int nc_put_n_byte(st_socket_t *p_socket, void *val, unsigned int n)
{
    int ret = 0;
    int i = 0;
    
    for (i = 0; i < n; i++){
        ret = nc_put_one_byte(p_socket, &val[i]);
        if (ret < 0){
            return ret;
        }
    }
}

int nc_send(st_socket_t *p_socket)
{
    return send(p_socket->socket, p_socket->send_buff, p_socket->cur_send_index, 0);
}

int nc_recv(st_socket_t *p_socket)
{
    return recv(p_socket->socket, p_socket->recv_buff, p_socket->max_buff_len, 0);
}

    编译连接之后生成libnetcom.so文件。

     以上代码在健壮性方面仍有不足,并且有很多特殊情况都没有考虑,后续再补充。下面写一个测试用例,测试库文件的基本功能。

    服务器端测试文件server.c:   

#include  <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>   
#include <arpa/inet.h>
#include <errno.h>

#define SERVER_PORT 6000
#define BUFF_LEN 1024
int main(int argc, char *argv[])
{
	int sock = 0, acc_sock = 0;
	struct sockaddr_in sockaddr, acc_sock_addr;
	int ret = 0;

	sock = socket(AF_INET, SOCK_STREAM, 0);

         memset(&sockaddr, 0, sizeof(struct sockaddr_in));
	sockaddr.sin_family = AF_INET;
	sockaddr.sin_addr.s_addr = INADDR_ANY;
	sockaddr.sin_port = htons(SERVER_PORT);

         ret = bind(sock,&sockaddr, sizeof(struct sockaddr_in));
	if (ret < 0){
		fprintf(stderr, "bind error--%s\n", strerror(errno));
		exit(-1);
	}

	ret = listen(sock, 10);
	if (ret < 0){
		fprintf(stderr, "listen error--%s\n", strerror(errno));
		exit(-1);
	}

	while (1)
	{
		socklen_t acc_addr_len = 0;
		char buff[BUFF_LEN] = {0}, send_buff[BUFF_LEN] = {0};

		acc_sock = accept(sock, &acc_sock_addr, &acc_addr_len);
		if (acc_sock < 0){
			fprintf(stdout, "accept error--%d\n", errno);
			exit(-1);
		}
                  printf("%s:%d connect to server\n", inet_ntoa(acc_sock_addr.sin_addr), acc_sock_addr.sin_port);

		ret = recv(acc_sock, buff, sizeof(buff), 0);
		sprintf(send_buff, "echo %s, %d", buff, ret);
		ret = send(acc_sock, send_buff, strlen(send_buff), 0); 
		printf("send %d byte:%s\n", ret, send_buff);
	}
	return 0;
}

   客户端测试文件client.c

   

#include "netcom/netcom.h"

#define IP "192.168.1.91"
#define PORT 6000

int main()
{
    int ret = 0;
    st_socket_t *p_socket = NULL;
    char buff[] = "hello";
    char ch = 0;
    char recv_buff[1024] = "";

    create_socket(&p_socket);
    ret = nc_conn(p_socket, IP, PORT);
    if (ret < 0){
        perror("nc_conn");
        exit(-1);
    }
    ret = nc_put_one_byte(p_socket, buff);
    strcpy(buff, "good");
    ret = nc_put_n_byte(p_socket, buff, strlen(buff));
    ret = nc_send(p_socket);

    ret = nc_recv(p_socket);
    printf("recv %d byte\n", ret);
    ret = nc_get_one_byte(p_socket, &ch);

    printf("ch = %c\n", ch);

    ret = nc_get_n_byte(p_socket, recv_buff, 10);
    printf("recv_buff = %s\n", recv_buff);
    return 0;
}


先执行服务器端,然后执行客户端之后:

[root@localhost echo]# ./server
255.127.0.0:60710 connect to server
send 13 byte:echo hgood, 5

root@szty-ThinkCentre-XXXX:lming_08# ./client
recv 13 byte
ch = e
recv_buff = cho hgood,

 

可以看出测试的效果还是不错的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值