(一)linux C语言TCP服务端/客户端简单编程步骤

头文件:
#ifndef _MYHEAD_H_
#define _MYHEAD_H_

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <dirent.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/msg.h>
#include <sys/sem.h>
#include <pthread.h>
#include <semaphore.h>
#include <poll.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/in.h>


#endif




由上图可知,TCP的服务端 5步就能完成基本功能。TCP客户端 3步就能完成基本功能。
接下来上基本代码:具体函数的操作等等再讲。
(为了使代码步骤更直观,这里不写错误处理语句)
//TCP服务器
#include"myhead.h"            //在linux下用man可以知道具体函数在什么头文件中,这里用myhead.h代替
#define LISTEN_NUM 5

int main()
{
	int sockfd,new_sockfd;
	int size;

	struct sockaddr_in saddr;
	struct sockaddr_in caddr;

	size = sizeof(struct sockaddr_in);

	/*初始化sockaddr_in saddr*/
	bzero(&saddr,sizeof(saddr));   //先清零saddr
	saddr.sin_family = AF_INET;		//AF_INET表示IPv4的类型
	saddr.sin_port = htons(8888);   //绑定8888端口
	saddr.sin_addr.s_addr = htonl(INADDR_ANY);   //绑定本机端口

	sockfd = socket(AF_INET,SOCK_STREAM,0);//返回-1表示失败;
	bind(sockfd,(struct sockaddr*)&saddr,size);//返回-1表示失败
	listen(sockfd,LISTEN_NUM);  //返回-1表示失败
	new_sockfd = accept(sockfd,(struct sockaddr*)&caddr,&size);//返回-1表示失败

	write(new_sockfd,"connect sucess!",sizeof("connect sucess"));

	return 0;
}

接下来到客户端:
//TCP客户端
#include"myhead.h"

int main()
{
	char buf[50];
	int sockfd,size;
	struct sockaddr_in saddr;

	size = sizeof(struct sockaddr_in);

	bzero(&saddr,sizeof(saddr));
	saddr.sin_family = AF_INET;
	saddr.sin_port = htons(8888); //服务器绑定的端口
	saddr.sin_addr.s_addr = inet_addr("192.168.152.128");//服务器的IP地址

	sockfd = socket(AF_INET,SOCK_STREAM,0); //创建一个套接字用于连接服务器,并且这个套接字可用作对服务器操作的文件描述符。
											//存储服务器的信息,返回-1失败	
	connect(sockfd,(struct sockaddr*)&saddr,size);//返回-1失败

	read(sockfd,buf,sizeof(buf));
	printf("%s\n",buf);
	return 0;
}

------------------------------------------------------------------------------------------------分割线----------------------------------------------------------------------------------------------------------------
接下来讲讲可能会疑惑的地方:
1.我们看到上面代码的一行:bind(sockfd,(struct sockaddr*)&saddr,size);
         saddr的类型明明已经定义为 sockaddr_in,为什么在这里又要强制转换为sockaddr呢?
         因为:sockadddr_in 其实是表明这个结构体是用于 IPv4 格式的,方便赋值。而传出去的时候,格式就是sockaddr的,可不管你是IPv4还是IPv6的。

2.htons 和 htonl和inet_addr:
        h代表主机host,n代表网络net,s代码短整型,htons代表把主机序换成网络序,处理短整型处理,例如端口号
        htonl则是用于处理long型,一般用于IP号,但一般IP号都用 inet_addr()来传了,唯独htonl(INADDR_ANY),这个表示随机选择本机的IP
        inet_addr(“IP号”)作用是把 点分十进制数 转换成 长整型数,点分十进制就是 一般ip的表现形式,如192.168.1.1

------------------------------------------------------------------------------------------------分割线----------------------------------------------------------------------------------------------------------------
服务端各函数:
     1.socket():
            socket()用于创建一个socket套接字,三个参数:domain(域),type(套接字类型),protocol(协议)
                domain常用的是 AF_INET和AF_INET6对应的是IPv4,IPv6协议域。
                type 常用的是 SOCK_STREAM 和 SOCK_DGRAM 对应的是 TCP 和 UDP。
                protocol 填0即可,填0他就会自动匹配合适的协议。

    2.bind():
            bind()的作用是 绑定 socket套接字和初始化的结构体(如 struct sockaddr_in),三个参数:要绑定的套接字和结构体,和结构体的字节大小
                  注意:这里需要把结构体转换成 struct sockaddr 类型了。因为套接字绑定此结构体后是要跟外部接触的。
   
    3.listen():
           listen()的作用是开始进行监听,就像电话刚刚安装好。有2个参数:分别是 服务器的套接字,连接等待队列的最大数目。
               第一个参数好理解,那第二个参数 “连接等待队列的最大数目”是什么意思呢?
               例如这个参数为5,并不是说这个服务器只能被5个客户端连接。而是服务端同一时刻能被连的只有5个客户端。

   4.accept():
           accept()的作用是 开始接收客户端的连接,如果listen像电话刚刚安装好,那accept就是一个等待别人来电的人,当没有人(客户端)连上,就一直阻塞,等待。
          当有人(客户端)连上,就继续往下执行。


客户端:
     1.socket():这个上面已经说了,这里就不赘述了。这里是创建一个套接字,用于连接服务端
     2.connect():
              作用是 把socket套接字连上服务端,若成功,操作socket套接字就等于往服务端操作,例如往socket套接字写内容,就是往服务端写内容。

  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要使用libevent库实现TCP/IP客户端服务端通信,可以按照以下步骤进行: 1. 引入libevent库的头文件和链接库。 ```c #include <event2/event.h> #include <event2/bufferevent.h> #include <event2/buffer.h> #include <event2/listener.h> #include <event2/util.h> #include <arpa/inet.h> #include <netinet/in.h> #include <sys/socket.h> #include <fcntl.h> #pragma comment(lib, "event.lib") #pragma comment(lib, "event_core.lib") #pragma comment(lib, "event_extra.lib") ``` 2. 创建服务端监听器并设置回调函数。 ```c struct event_base* base = event_base_new(); // 创建event_base对象 // 创建监听器 struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_ANY); sin.sin_port = htons(8888); struct evconnlistener* listener = evconnlistener_new_bind(base, accept_cb, NULL, LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE, 10, (struct sockaddr*)&sin, sizeof(sin)); // 设置回调函数 void accept_cb(struct evconnlistener* listener, evutil_socket_t fd, struct sockaddr* addr, int len, void* ptr) { struct event_base* base = evconnlistener_get_base(listener); struct bufferevent* bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE); bufferevent_setcb(bev, read_cb, NULL, event_cb, NULL); bufferevent_enable(bev, EV_READ | EV_WRITE); } ``` 3. 创建客户端并连接到服务端。 ```c struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(8888); inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr); // 创建事件对象 struct event_base* base = event_base_new(); struct bufferevent* bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE); bufferevent_setcb(bev, read_cb, NULL, event_cb, NULL); // 连接服务端 bufferevent_socket_connect(bev, (struct sockaddr*)&sin, sizeof(sin)); ``` 4. 设置读写回调函数。 ```c void read_cb(struct bufferevent* bev, void* ctx) { struct evbuffer* input = bufferevent_get_input(bev); size_t len = evbuffer_get_length(input); char* data = (char*)malloc(len + 1); memset(data, 0, len + 1); evbuffer_copyout(input, data, len); printf("recv: %s\n", data); free(data); evbuffer_drain(input, len); } void event_cb(struct bufferevent* bev, short events, void* ctx) { if (events & BEV_EVENT_EOF) { printf("connection closed\n"); } else if (events & BEV_EVENT_ERROR) { printf("some other error\n"); } bufferevent_free(bev); } ``` 5. 启动事件循环。 ```c event_base_dispatch(base); ``` 这样就可以使用libevent库实现TCP/IP客户端服务端通信了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值