Linux socket网络编程基础 tcp和udp

时间:2022-11-17 10:20:14

Socket TCP网络通信编程

首先,服务器端需要做以下准备工作:

  (1)调用socket()函数。建立socket对象,指定通信协议。

  (2)调用bind()函数。将创建的socket对象与当前主机的某一个IP地和端口绑定。

  (3)调用listen()函数。使socket对象处于监听状态,并设置监听队列大小。

客户端需要做以下准备工作:

  (1)调用socket()函数。建立socket()对象,指定相同通信协议。

  (2)应用程序可以显式的调用bind()函数为其绑定IP地址和端口,当然,也可以将这工作交给TCP/IP协议栈。

接着建立通信连接:

  (1)客户端调用connect()函数。向服务器端发出连接请求。

  (2)服务端监听到该请求,调用accept()函数接受请求,从而建立连接,并返回一个新的socket文件描述符专门处理该连接。

然后通信双方发送/接收数据:

  (1)服务器端调用write()或send()函数发送数据,客户端调用read()或者recv()函数接收数据。反之客户端发送数据,服务器端接收数据。

  (2)通信完成后,通信双方都需要调用close()或者shutdown()函数关闭socket对象。

 

类比电话通信,面向连接的socket通信实现图

 

Linux socket网络编程基础 tcp和udp

 

展示一个代码示例:

服务端:

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

static void usage(const char *proc)
{
printf(
"Please use :%s [IP] [port]\n",proc);
}

void thread_run(void *arg)
{
printf(
"creat a new thread\n");
int fd = (int)arg;
char buf[1024];

while(1){
memset(buf,
'\0',sizeof(buf));
ssize_t _s
= read(fd,buf,sizeof(buf) - 1);
if(_s > 0){
buf[_s]
= '\0';
printf(
"client say : %s\n",buf);
}
memset(buf,
'\0',sizeof(buf));
printf(
"please Enter: ");
fflush(stdout);
ssize_t _s2
= read(0,buf,sizeof(buf) - 1);
if(_s2 > 0){
write(fd,buf,strlen(buf));
}
}
}

int main(int argc,char *argv[])
{
if(argc != 3){
usage(argv[
0]);
exit(
1);
}

//1.creat socket

int sock = socket(AF_INET,SOCK_STREAM,0);
if(sock < 0){
perror(
"creat socket error\n");
return 1;
}

struct sockaddr_in local;
local.sin_family
= AF_INET;
local.sin_port
= htons(atoi(argv[2]));
local.sin_addr.s_addr
= inet_addr(argv[1]);

//2.bind

if(bind(sock,(struct sockaddr*)&local,sizeof(local)) < 0){
perror(
"bind error\n");
close(sock);
return 2;
}

//3.listen

if(listen(sock,10) < 0){
perror(
"listen error\n");
close(sock);
return 3;
}

printf(
"bind and listen success!wait accept...\n");

//4.accept

struct sockaddr_in peer;
socklen_t len
= sizeof(peer);
while(1){

int fd = accept(sock,(struct sockaddr*)&peer ,&len);

if(fd < 0){
perror(
"accept error\n");
close(sock);
return 4;
}

printf(
"get connect,ip is : %s port is : %d\n",inet_ntoa(peer.sin_addr),ntohs(peer.sin_port));

pthread_t id;
pthread_create(
&id,NULL,thread_run,(void*)fd);

pthread_detach(id);

}
close(sock);
return 0;
}

客户端:

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

static void usage(const char *proc)
{
printf(
"please use : %s [ip] [port]\n",proc);
}
int main(int argc,char *argv[])
{
if( argc != 3 ){
usage(argv[
0]);
exit(
1);
}

int sock = socket(AF_INET,SOCK_STREAM,0);
if(sock < 0){
perror(
"socket error");
return 1;
}

struct sockaddr_in remote;
remote.sin_family
= AF_INET;
remote.sin_port
= htons(atoi(argv[2]));
remote.sin_addr.s_addr
= inet_addr(argv[1]);


int ret = connect(sock,(struct sockaddr*)&remote,sizeof(remote));
if(ret < 0){
printf(
"connect failed:%s\n",strerror(errno));
return 2;
}

printf(
"connect success!\n");

char buf[1024];
while(1){
memset(buf,
'\0',sizeof(buf));
printf(
"please enter:");
fflush(stdout);
ssize_t _s
= read(0,buf,sizeof(buf)-1);
if(_s > 0){
buf[_s
- 1] = '\0';
write(sock,buf,strlen(buf));
_s
= read(sock,buf,sizeof(buf)-1);
if(_s > 0){
if(strncasecmp(buf,"quit",4) == 0){
printf(
"qiut\n");
break;
}
buf[_s
-1] = '\0';
printf(
"%s\n",buf);
}
}
}
close(sock);
return 0;
}

 

UDP网络通信编程

 客户不与服务器建立链接,而是管使用sendto函数给服务器发送数据报,其中必须指定目的地址(即服务器地址)作为参数。类似的,服务器不接受来自客户的连接,而只管调用

revcfrom函数等待来自某个客户数据的到达。revcfrom将与所接受到的数据报一道返回客户的协议地址,因此服务器可以把响应发送给正确的客户。

 

Linux socket网络编程基础 tcp和udp

 

Linux socket网络编程基础 tcp和udp服务端示例 Linux socket网络编程基础 tcp和udp
//服务端代码示例:

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

int main(int argc,char *argv[])
{
if(argc != 3){
printf(
"Please Enter: %s [ip] [port]",argv[0]);
return 1;
}

int sock = socket(AF_INET,SOCK_DGRAM,0);
if(sock < 0){
perror(
"socket error");
return 2;
}

struct sockaddr_in local;
local.sin_family
= AF_INET;
local.sin_port
= htons(atoi(argv[2]));
local.sin_addr.s_addr
= inet_addr(argv[1]);


if(bind(sock,(struct sockaddr*)&local,sizeof(local)) < 0){
perror(
"bind error");
return 3;
}

int done = 0;
struct sockaddr_in peer;
socklen_t len
= sizeof(peer);

char buf[1024];
while(!done){
memset(buf,
'\0',sizeof(buf));
recvfrom(sock,buf,
sizeof(buf),0,(struct sockaddr*)&peer,&len);
printf(
"#########################\n");
printf(
"get a client,socket: %s:%d\n",inet_ntoa(peer.sin_addr),ntohs(peer.sin_port));

printf(
"client : %s ,echo client!\n",buf);
printf(
"#########################\n");
sendto(sock,buf,
sizeof(buf),0,(struct sockaddr*)&peer,len);

}
return 0;
}