socket通讯编程

socket通讯编程

在这里插入图片描述
传输层协议。包括传输控制协议TCP和用户数据报文协议UDP。
传输控制协议(TCP)。由于IP 提供非连接型传递服务,因此TCP应为应用程序存取网络创造了条件,使用可靠的面向连接的传输层服务。该协议为建立网际上用户进程之间的对话负责。此外,还确保两个以上进程之间的可靠通信。它所提供的功能如下:
1.监听输入对话建立请求。
2.请求另一网络站点对话。
3.可靠的发送和接收数据。
4.适度的关闭对话。
三次握手:
可以简化为对讲机:
A->B(发送消息确认B是否可以收到)
B->A(发送信息,回复自己是否可以收到,并且确定对方是否可以接收到自己的消息)
A->B(发送消息回应B自己可以收到消息)

A–协议/约定—>B
B<—协议/约定—A
有两个地址
源地址:数据从哪来
目的地址:数据往哪去

在这里插入图片描述

由此可见UDP并不安全 Socket既是一种特殊的IO,它也是一种文件描述符。一个完整的Socket

都有一个相关描述{协议,本地地址,本地端口,远程地址,远程端口};每一个Socket 有一个本地的唯一Socket 号,由操作系统分配。
在linux上实现C/S模型
servce.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define MAXLINE 80
#define SERV_PORT 8000
int main(void)
{
struct sockaddr_in servaddr, cliaddr;
socklen_t cliaddr_len;
int listenfd, connfd;
char buf[MAXLINE];
char str[INET_ADDRSTRLEN];
int i, n;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
listen(listenfd, 20);
printf("Accepting connections ...\n");
while (1) {
cliaddr_len = sizeof(cliaddr);
connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);
n = read(connfd, buf, MAXLINE);
printf("received from %s at PORT %d\n",
inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),
ntohs(cliaddr.sin_port));
for (i = 0; i < n; i++)
buf[i] = toupper(buf[i]);
write(connfd, buf, n);
close(connfd);
}
 }

client.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define MAXLINE 80
#define SERV_PORT 8000
int main(int argc, char *argv[])
{
struct sockaddr_in servaddr;
char buf[MAXLINE];
int sockfd, n;
char *str;
if (argc != 2) {
fputs("usage: ./client message\n", stderr);
exit(1);
}
str = argv[1];
sockfd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
servaddr.sin_port = htons(SERV_PORT);
connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
write(sockfd, str, strlen(str));
n = read(sockfd, buf, MAXLINE);
printf("Response from server:\n");
write(STDOUT_FILENO, buf, n);
close(sockfd);
return 0;
}

在QT上实现客户端,linux上实现服务端。
1.查找linux上的地址,虚拟机的网络设置为桥接
2.关闭防火墙

QT:
首先要在pro上加上network
在这里插入图片描述
widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QtGui/QWidget>
#include <QtNetwork>
#include <QTcpSocket>
#include <QPushButton>
#include <QLineEdit>
#include <QLabel>

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
private:

    QLabel *Ip_label;
    QLabel *Port_label;

    QLineEdit *Ip_Edit;
    QLineEdit *Port_Edit;

    QPushButton *connect_btn;
    QPushButton *close_btn;

    QTcpSocket *tcpclient;
private slots:
    void connect_slot();
    void slot_connected();

};

#endif // WIDGET_H

widget.cpp

#include "widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{

    Ip_label =new QLabel(this);
    Ip_label->move(70,80);
    Ip_label->setText("IP");

    Port_label=new QLabel(this);
    Port_label->move(70,130);
    Port_label->setText("port");

    Ip_Edit =new QLineEdit(this);
    Ip_Edit->move(140,80);
    Ip_Edit->setPlaceholderText("please input ip");

    Port_Edit=new QLineEdit(this);
    Port_Edit->move(140,130);
    Port_Edit->setPlaceholderText("please input port");

    connect_btn =new QPushButton(this);
    connect_btn->move(70,200);
    connect_btn->setText("yes");


    close_btn=new QPushButton(this);
    close_btn->move(220,200);
    close_btn->setText("back");





    connect(connect_btn,SIGNAL(clicked()),this,SLOT(connect_slot()));
}

Widget::~Widget()
{

}

void Widget::connect_slot()
{
    tcpclient =new QTcpSocket(this);    //初始化socket
//    tcpclient->abort(); //终止之前的连接,重置套接字
    this->tcpclient->connectToHost(Ip_Edit->text(),6666);
//    connect(tcpclient,SIGNAL(connected()),this,SLOT(slot_connected()));
}
void Widget::slot_connected()
{

}

main.cpp

#include <QtGui/QApplication>
#include "widget.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

LINUX:

#include <stdlib.h>

#include <stdio.h>  

#include <errno.h>  

#include <string.h>  

#include <netdb.h>  

#include <sys/types.h>  

#include <netinet/in.h>  

#include <sys/socket.h>    



#define portnumber 6666   



int main(int argc, char *argv[])

{   

	int sockfd,new_fd;   

	struct sockaddr_in server_addr;   

	struct sockaddr_in client_addr;   

	int sin_size;   

	int nbytes;  

	char buffer[1024];     

	

	/* 服务器端开始建立sockfd描述符 */   

	if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) // AF_INET:IPV4; SOCK_STREAM:TCP  

	{    

		fprintf(stderr,"Socket error:%s\n\a",strerror(errno));    

		exit(1);   

	}    

	

	//设置Socket属性:SO_REUSEADDR:允许在bind过程中本地地址重复使用   

	int iSockopt = 1;

	if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, 

		(const char *)&iSockopt, sizeof(int)) < 0 )

	{   

		close(sockfd);   

		return -1;   

	}

	

	

	/* 服务器端填充 sockaddr结构 */   

	bzero(&server_addr,sizeof(struct sockaddr_in)); // 初始化,置0  

	server_addr.sin_family=AF_INET;                 // Internet

	server_addr.sin_addr.s_addr=INADDR_ANY;  //INADDR_ANY 表示可以接收任意IP地址的数据,即绑定到所有的IP  

	//server_addr.sin_addr.s_addr=inet_addr("192.168.1.1");  

	//用于绑定到一个固定IP,inet_addr用于把数字加格式的ip转化为整形ip  

	server_addr.sin_port=htons(portnumber);    // (将本机器上的short数据转化为网络上的short数据)端口号

	

	/* 捆绑sockfd描述符到IP地址 */   

	if(bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)   

	{    

		fprintf(stderr,"Bind error:%s\n\a",strerror(errno));    

		exit(1);   

	}    

	/* 设置允许连接的最大客户端数 */   

	if(listen(sockfd,5)==-1)   

	{    

		fprintf(stderr,"Listen error:%s\n\a",strerror(errno));    

		exit(1);   

	}

	while(1)   

	{    

		/* 服务器阻塞,直到客户程序建立连接 */    

		sin_size=sizeof(struct sockaddr_in);    

		if((new_fd=accept(sockfd,(struct sockaddr *)(&client_addr),&sin_size))==-1)    

		{     

			fprintf(stderr,"Accept error:%s\n\a",strerror(errno));     

			exit(1);    

		}    

		fprintf(stderr,"Server get connection from %s\n",inet_ntoa(client_addr.sin_addr)); // 将网络地址转换成.字符串

		

		

		if((nbytes=read(new_fd,buffer,1024))==-1)    

		{     

			fprintf(stderr,"Read Error:%s\n",strerror(errno));     

			exit(1);    

		} 

  
		buffer[nbytes]='\0';   

		printf("Server received %s\n",buffer);      //这个通讯已经结束     

		close(new_fd);    /* 循环下一个 */   

	}    /* 结束通讯 */

	

	close(sockfd);   

	exit(0);  

}

makefile

.PHONY: clean all
CC  = gcc
CXX = g++ 
CPPFLAGS = -Wall -Wno-deprecated
LDFLAGS  = -lpthread -lrt -lsqlite3

BINSRCS	:= main.cpp

SRCS 	:= $(wildcard *.cpp)
SRCS	:= $(filter-out $(BINSRCS),$(SRCS))

BIN = main
all: $(BIN)

main: $(SRCS) main.cpp
	$(CXX) $(CPPFLAGS) $^ -o $@  $(LDFLAGS)


	
%.o:%.cpp  
	$(CXX) $(CPPFLAGS) -c $<  	

%.o:%.c 
	$(CC) -c $<

clean:
	-rm -rf $(BIN)  *.o
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值