头文件:

#ifndef _MYHEAD_H_

#define _MYHEAD_H_

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#endif

服务器端 c 语言 java c语言服务器端开发_linux c 服务端编程

由上图可知,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套接字写内容,就是往服务端写内容。